UI and HTML

The user interface (UI) of a Shiny application is HTML, but in most cases, you will use wrapper functions that make it easier to create the HTML. To get the most out of user interfaces, it’s important to understand the relationship between Shiny’s UI functions and the HTML that they generate.

UI components are available via the shiny.ui submodule. At the most basic level, you can create HTML tags by calling a correspondingly named function. For example, to create a <div> tag, you would call ui.div().

#| components: [editor, cell]

from shiny import ui
ui.div("Hello!")

Tags can be nested:

#| components: [editor, cell]

ui.div("Hello", ui.span("World"), "!")

You can provide tag attributes (like href) with named arguments. Note that in Python, named arguments must go after unnamed arguments.

#| components: [editor, cell]

ui.a("Help", href="help.html")

Another way to do it is by passing in a dictionary of attributes.

#| components: [editor, cell]

ui.a({"href": "help.html"}, "Help")

In Python, there are some reserved keywords which can’t be used as argument names, such as class. To get around this, you can either use a dictionary as above, or append an underscore to the argument. If there’s a trailing _, it will be stripped off when creating the tag object.

#| components: [editor, cell]

# Two ways of doing the same thing
ui.a({"href": "help.html", "class": "help-link"}, "Help")
ui.a("Help", href="help.html", class_="help-link")

For convenience, common tags like div, span, and a are available directly from the ui submodule. All HTML tags are also available via ui.tags, so if you need to use a less common tag like li, you can use ui.tags.li()

Sometimes it it useful to return several tag objects together, but in a way where they are not nested within another tag. You can use a TagList() for this:

#| components: [editor, cell]

ui.TagList(
    ui.div("Hello"),
    ui.span("World"),
    "!"
)

UI components

Most Shiny UI code doesn’t require you to use functions like div() to write raw HTML. Instead, there are convenience functions that wrap up the HTML tags.

For example, ui.input_checkbox() generates the following HTML:

#| components: [editor, cell]

ui.input_checkbox("enable", "Enable?")

A complete UI for a Shiny app will put components in a page_ function. Here is a simple page with a checkbox input and a text output.

#| components: [editor, cell]

from shiny import ui

ui.page_fluid(
    ui.input_checkbox("enable", "Enable?"),
    ui.output_text_verbatim("txt"),
)

Broadly speaking, there are three categories of UI components: layout components, inputs, and outputs. The page_fluid() is a layout component, and it contains one input and one output.

Shiny for Python compared to R

In Shiny for Python, the page-related functions start with page_, the input-related functions start with input_, and the output-related functions start with output_. This is different from Shiny for R, where the functions are named fluidPage, checkboxInput, and textOutput.

This is what the application looks like. Note that there’s no server logic, so it doesn’t actually do anything yet.

#| standalone: true
#| layout: vertical

from shiny import App, ui

app_ui = ui.page_fluid(
    ui.input_checkbox("enable", "Enable?"),
    ui.h3("Is it enabled?"),
    ui.output_text_verbatim("txt", placeholder=True),
)

app = App(app_ui, None)