UI Layout

Goals

You can fill your app with content, but can you organize it?

Tip

This section is a bit of a survey. Just know:

  • That these exist
  • What it feels like to use them
  • And where to rediscover them when you need them

Why care about UI design?

  • It’s what your stakeholders care about!
  • Good UI design simplifies your application code
  • Intuitive UIs mean fewer questions

Introduction

Agenda

  • Introduction

  • Cards

  • Sidebars

  • Value boxes

  • Rows and columns

  • Tabsets

  • Navbars

  • Two advanced topics

  • Recap

Where we’re headed

Where we’re starting

How we will get there

Any guesses which module we will use?

An app is a web page. ui functions emit HTML.

  • non-reactive
  • can be styled with CSS

There are even functions to insert HTML


ui.HTML('<a href="https://posit.co">Visit posit.co</a>')


ui.tags.a("Visit posit.co", href="https://posit.co")

Cards

Agenda

  • Introduction

  • Cards

  • Sidebars

  • Value boxes

  • Rows and columns

  • Tabsets

  • Navbars

  • Two advanced topics

  • Recap

Common tasks

Cards Cards

Tabsets Tabsets

Sidebars Sidebars

Navbars Navbars

Rows and Columns Rows and Columns

Filling page Filling the page

Your turn

Cards

  • Cards are just small boxes which contain other elements
  • Useful for grouping inputs and outputs
  • “Dashboards” are just web apps in boxes
  • Called with with ui.card():
  • Cards can take ui.card_header() and ui.card_footer()

What is with?

Can any of our Python users explain?

with ui.card(full_screen=True):
    ui.card_header("This is the header")
    ui.p("This is the body.")
    ui.p("This is still the body.")
    ui.card_footer("This is the footer")

Context managers

with is a convenient way to group multiple functions within a single context.

with ui.card(full_screen=True):
    ui.card_header("This is the header")
    ui.p("This is the body.")
    ui.p("This is still the body.")
    ui.card_footer("This is the footer")

Let’s demo with with sidebars

with ui.sidebar():
    "App level sidebar"


with ui.card():
    with ui.layout_sidebar():
        with ui.sidebar():
            "Card level sidebar"

Aside - Titles

Adding a title to an App also helps to give it structure. Add titles with

ui.page_opts(title = "My Title")

Sidebars

Agenda

  • Introduction

  • Cards

  • Sidebars

  • Value boxes

  • Rows and columns

  • Tabsets

  • Navbars

  • Two advanced topics

  • Recap

Your turn

Value boxes

Agenda

  • Introduction

  • Cards

  • Sidebars

  • Value boxes

  • Rows and columns

  • Tabsets

  • Navbars

  • Two advanced topics

  • Recap

Is there a better way to emphasize numbers and values?

with ui.card():
    ui.card_header( "Important Value")
    9

An “output” that is a layout device

Components

Value boxes can have:

  1. An icon
  2. A value
  3. Supporting text
  4. A fill color (a “theme”)

Value boxes in action

Tip

The faicons package provides fontawesome icons.

Your turn

Rows and columns

Agenda

  • Introduction

  • Cards

  • Sidebars

  • Value boxes

  • Rows and columns

  • Tabsets

  • Navbars

  • Two advanced topics

  • Recap

Rows and columns

What if you want to customize your layout more generally?

  • What about?
    • Different screen sizes?
    • Mobile browsers?
    • Different zoom levels?
    • Nested UI containers?
  • What we need is a responsive way to specify the size of things
  • Enter ui.layout_columns()

ui.layout_columns() demo

Columns are built on the Bootstrap grid

  • Assign an integer width for each column
  • 1 unit = 1/12 of the available space
  • Negative widths insert an empty column (white space)
  • When cumulative widths exceed 12, Shiny begins a new row.
  • You can nest layout_column functions

Quiz - What col_widths would create this layout?

  • Assign an integer width for each column
  • 1 unit = 1/12 of the available space
  • Negative widths insert an empty column (white space)
  • When cumulative widths exceed 12, Shiny begins a new row.
  • You can nest layout_column functions

Quiz - What col_widths would create this layout?

  • Assign an integer width for each column
  • 1 unit = 1/12 of the available space
  • Negative widths insert an empty column (white space)
  • When cumulative widths exceed 12, Shiny begins a new row.
  • You can nest layout_column functions

Quiz - What col_widths would create this layout?

  • Assign an integer width for each column
  • 1 unit = 1/12 of the available space
  • Negative widths insert an empty column (white space)
  • When cumulative widths exceed 12, Shiny begins a new row.
  • You can nest layout_column functions

Row heights

row_heights are proportional to each other

Your turn

Tabsets

Agenda

  • Introduction

  • Cards

  • Sidebars

  • Value boxes

  • Rows and columns

  • Tabsets

  • Navbars

  • Two advanced topics

  • Recap

To organize panels in the same space

  1. Use with ui.nav_panel() to create a panel with a title and contents.
with ui.nav_panel("A"):
    "Panel A content"
  1. Choose a function to provide navigation between panels.

Navbars

Agenda

  • Introduction

  • Cards

  • Sidebars

  • Value boxes

  • Rows and columns

  • Tabsets

  • Navbars

  • Two advanced topics

  • Recap

If there are top level Nav Panels (with ui.nav_panel("A"):), Shiny will automatically group them into a multi-page app with a navbar.

Tip

Use ui.page_opts() to provide a title for the navbar.
Call ui.nav_spacer() to push the panel labels to the right side of the navbar.

Navbars

Your turn

Two advanced topics

Agenda

  • Introduction

  • Cards

  • Sidebars

  • Value boxes

  • Rows and columns

  • Tabsets

  • Navbars

  • Two advanced topics

  • Recap

Can the UI itself react to the user?

Yes, in several ways.

Explore this topic here.

Planning for screen size

Would you like to control how elements resize as the viewer’s screen size changes?

Explore this topic here.

Recap

Agenda

  • Introduction

  • Cards

  • Sidebars

  • Value boxes

  • Rows and columns

  • Tabsets

  • Navbars

  • Two advanced topics

  • Recap

Common Tasks

Cards ui.card()

Tabsets ui.navset_tab()

Sidebars ui.sidebar()

Navbars ui.navset_bar()

Rows and Columns ui.layout_columns()

with ui.nav_panel("A"):
    Contents