DataLens

Text, titles, markdown, and displaying data

Structure a page with headings and markdown, highlight numbers with metrics, signal status with coloured messages, and show tables the right way.

Level: Foundations · 7 min read

Practise this module

The questions for this lesson run in your browser and check your answer straight away.

The idea

A dashboard is mostly communication: a clear title, a few headline numbers, a sentence of context, a table for the details. Streamlit has a small set of elements for each job. Picking the right one makes a page scannable, so people find the number they came for in two seconds.

Headings and text

The owner opens the weekly report on their phone and should know straight away what it covers, when it was refreshed, and what the main points are. Streamlit has a small set of text elements for structuring a page like that:

import streamlit as st

st.title("Toko Kita: weekly report")
st.caption("Completed orders, 1 to 7 July 2024 · refreshed 08:00 WIB")
st.header("Sales")
st.subheader("By channel")
st.text("Plain, fixed-width text.")
st.markdown("Revenue is **up 12%**, driven by the *web* channel.")
ElementUse for
st.titlethe page name, once, at the top
st.header / st.subheadersections and sub-sections
st.markdownsentences with bold, italics, lists, links
st.captionsmall grey context: source, period, refresh time
st.textfixed-width text, rarely needed
st.divider()a horizontal line between sections

Markdown in one call

st.markdown understands the same Markdown you've seen in this site's lessons:

import streamlit as st

st.markdown("""
### This week
- **Revenue:** Rp 11.8M (completed)
- **Top product:** USB-C Hub
- Full data in the [shared drive](https://example.com)
""")

Triple-quoted strings let you write several lines naturally. st.write("...") also renders Markdown, which is why it worked for text in the first module.

Metrics: the headline numbers

st.metric shows a big number with an optional change underneath:

import streamlit as st

st.metric("Revenue", "Rp 11.8M", delta="12%")
st.metric("Cancelled orders", 10, delta=3, delta_color="inverse")

The delta is green when positive and red when negative. For numbers where up is bad (cancellations, costs, complaints), delta_color="inverse" flips the colours, so +3 cancellations shows red.

A row of metrics at the top is the classic dashboard header; the layout module shows how to put them side by side.

Status messages

Coloured boxes signal how the reader should feel about something:

import streamlit as st

st.success("All 26 completed orders were delivered.")
st.info("Data for June is still being finalised.")
st.warning("3 orders are pending for more than 7 days.")
st.error("The payment provider feed failed at 03:00.")

Use them sparingly. If everything is a warning, nothing is.

Showing data

At some point the owner will want to see the actual numbers behind the headline, like revenue per category. Streamlit has two ways to show a DataFrame, and they suit different situations:

import streamlit as st
import pandas as pd

sales = pd.read_csv("sales.csv")
by_category = (sales[sales["status"] == "completed"]
               .groupby("category", as_index=False)["revenue"].sum()
               .sort_values("revenue", ascending=False))

st.subheader("Interactive table")
st.dataframe(by_category, hide_index=True)

st.subheader("Static table")
st.table(by_category)

st.json displays dictionaries and API responses, collapsible and readable:

import streamlit as st

st.json({"order_id": "NG-105", "status": "pending", "items": [{"sku": "KT-POUR", "qty": 1}]})

st.write: the Swiss army knife

st.write looks at what you give it and picks a display: text becomes Markdown, a DataFrame becomes a table, a dict becomes JSON, a Plotly figure becomes a chart. It also takes several arguments: st.write("Total:", 42).

It's great while exploring. In finished apps, prefer the specific function (st.markdown, st.dataframe, st.metric): the code says exactly what appears, and you get their extra options.

Why this matters for clean code

A readable page has the same structure as readable code: a clear name (title), sections (headers), the important things first (metrics), details last (tables). Choosing the specific element over st.write is the UI version of choosing a precise name over x: the next person knows exactly what you meant.

Recap

Practise this module

The questions for this lesson run in your browser and check your answer straight away.

Next: Input widgets (button, slider, selectbox, text_input) →