Trends over time with dates on the axis, several series, targets and thresholds — and a hover crosshair on every point.
A revenue card
Pass dates as x values: the axis formats itself for the span it covers.
Monthly recurring revenue
$99.7k
+62.9% in 12 months
defdollars(value:float)->str:returnf"${value/1000:.0f}k"defmrr()->list[tuple[date,float]]:months=[date(2025,m,1)forminrange(9,13)]+ \
[date(2026,m,1)forminrange(1,9)]values=[61200,63900,66100,70400,72800,75100,79600,83300,86900,91800,95200,99700]returnlist(zip(months,values,strict=True))defmrr_card()->None:withui.card(padding="md"),ui.vstack(gap="sm"):withui.hstack(justify="between",align="start",wrap=True):withui.vstack(gap="none"):ui.text("Monthly recurring revenue",size="sm",color="muted")ui.heading("$99.7k",level=3,size="2xl")ui.badge("+62.9% in 12 months",color="success",variant="soft",size="sm",icon_left="trending-up")ui.line_chart(data=mrr(),y_format=dollars,area_fill=True,size="sm")
Several series
One Series per line, sharing the same x values. The legend and the colours follow the order you give.
Weekly sign-ups by channel
937
0100200300400500Jun 21Jul 14
defsignups_by_channel()->list[Series]:weeks=[date(2026,6,1)+timedelta(weeks=i)foriinrange(10)]return[Series("Organic",list(zip(weeks,[320,341,338,362,390,402,398,431,455,470],strict=True))),Series("Paid",list(zip(weeks,[210,236,228,251,244,270,302,288,296,315],strict=True))),Series("Referral",list(zip(weeks,[88,92,101,97,112,126,131,140,138,152],strict=True))),]defmulti_series()->None:withui.card(padding="md"),ui.vstack(gap="sm"):withui.vstack(gap="none"):ui.text("Weekly sign-ups by channel",size="sm",color="muted")ui.heading("937",level=3,size="2xl")ui.line_chart(data=signups_by_channel())
Against a threshold
Straight segments and dots for discrete measures, and a reference line for the objective.
deflatency()->list[tuple[date,float]]:days=[date(2026,9,1)+timedelta(days=i)foriinrange(14)]values=[212,198,225,240,231,318,342,267,229,214,205,221,236,219]returnlist(zip(days,values,strict=True))defthreshold()->None:withui.card(padding="md"),ui.vstack(gap="sm"):withui.hstack(justify="between",align="start",wrap=True):withui.vstack(gap="none"):ui.text("API latency · p95",size="sm",color="muted")ui.heading("219 ms",level=3,size="2xl")ui.badge("2 breaches this month",color="warning",variant="soft",size="sm",icon_left="triangle-alert")ui.line_chart(data=latency(),color="warning",smooth=False,show_dots=True,y_unit="ms",size="sm",reference_lines=[Reference(300,"SLO","error")])
This year against last year
Pin the comparison series to muted so the current one carries the colour.
Monthly active users, in thousands
3 k4 k5 k6 k7 k8 kFeb 02May 28
defactive_users()->list[Series]:months=[date(2026,m,1)forminrange(1,10)]return[Series("This year",list(zip(months,[4.1,4.4,4.9,5.2,5.8,6.1,6.0,6.7,7.2],strict=True))),Series("Last year",list(zip(months,[3.2,3.3,3.6,3.5,3.9,4.0,3.8,4.2,4.4],strict=True)),color="muted"),]defcomparison()->None:withui.card(padding="md"),ui.vstack(gap="sm"):ui.text("Monthly active users, in thousands",size="sm",color="muted")ui.line_chart(data=active_users(),show_gridlines=False,y_unit="k",size="sm")
A range that reloads the chart
The toggle writes the period to a server state; only the chart that reads it is rendered again.
Daily visits
1.6k1.8k2k2.2k2.4kSep 10Sep 21
classTraffic(PageState):period:str=field(default="30")defchange_period(state:Traffic)->None:"""The typed parameter receives the toggle's value; nothing else to do."""defvisits(days:int)->list[tuple[date,float]]:start=date(2026,9,28)-timedelta(days=days-1)points=[]foriinrange(days):day=start+timedelta(days=i)weekend=320ifday.weekday()>=5else0points.append((day,2100+160*math.sin(i/5)+4*i-weekend))returnpoints@refreshable(deps=[Traffic])deftraffic_chart()->None:days=int(Traffic().period)ui.line_chart(data=visits(days),color="info",area_fill=True,y_format="abbreviated",size="sm")deflive_range()->None:withui.card(padding="md"),ui.vstack(gap="sm"):withui.hstack(justify="between",align="center",wrap=True):ui.text("Daily visits",size="sm",color="muted")ui.toggle_group(value=Traffic().period,on_change=change_period,size="sm",options=[("7","7 days"),("30","30 days"),("90","90 days")])traffic_chart()