Dashboard

A responsive analytics dashboard with zero hand-written CSS or JavaScript.

dashboard/
├── app.py               # composition root
├── models/              # metrics.py (the data)
├── services/            # metrics.py (MetricsService, also a JSON API)
└── views/
    ├── components/      # sidebar, stat_card, region_chart, recent_orders
    ├── pages/           # overview.py
    └── styles/

1. Data first

class MetricsService(Service):
    """Sales metrics. A real app would query a database or a warehouse here."""

    @remote(method="GET")
    def overview(self, days: int = 30, seed: int = 0) -> Metrics:
        """Revenue, orders, conversion, refunds and recent orders for the last ``days`` days."""
        if days not in PERIODS:
            raise FieldError("days", f"Choose one of: {', '.join(map(str, PERIODS))}")
        rng = random.Random(days * 1000 + seed)  # deterministic fake numbers; a new seed changes them
        by_region = {region: rng.randint(4, 40) * days * 10 for region in REGIONS}
        recent = [
            Order(f"#{rng.randint(10_000, 99_999)}", rng.choice(CUSTOMERS), rng.choice(REGIONS), rng.randint(20, 900))
            for _ in range(6)
        ]
        return Metrics(
            days=days,
            revenue=sum(by_region.values()),
            orders=rng.randint(80, 140) * days,
            conversion=round(rng.uniform(1.5, 4.5), 2),
            refunds=rng.randint(0, 3) * days,
            by_region=by_region,
            recent=recent,
        )

Components never fetch data themselves here: the page loads Metrics and passes plain values down as props. That keeps components easy to reuse and to test.

2. A sidebar that moves

class Sidebar(Component):
    """Beside the content on desktop and above it on narrow screens (see ``SIDEBAR``).
    The theme buttons run in the browser with ``js.set_theme``: no server round trip."""

    def render(self):
        links = [
            Link(label, href="#", style=NAV_LINK, aria_current="page" if label == "Overview" else None)
            for label in SECTIONS
        ]
        themes = [
            Button(mode.capitalize(), size="sm", variant="outline", on_click=js.set_theme(mode))
            for mode in ("light", "dark", "system")
        ]
        return Nav(
            Text("◆ Acme", weight=700, size="lg"),
            Column(*links, gap="xs", style=NAV_LIST),
            Spacer(),
            Text("Theme", muted=True, size="sm"),
            Row(*themes, gap="xs", wrap=True),
            aria_label="Main",
            style=SIDEBAR,
        )

viewport={"narrow": ...} changes the style below 1024px: the sidebar loses its full height and its right border when it moves above the content.

3. A chart that measures itself

class RegionChart(Component):
    """A bar chart made of plain elements. It adapts to its *own* width with a container query:
    in a narrow card the amounts are hidden, whatever the size of the screen."""

    data: dict[str, int]

    def render(self):
        top = max(self.data.values())
        rows = [
            h(
                "li",
                Text(region, size="sm", style=BAR_LABEL),
                h("div", h("div", style=BAR | Style(width=f"{value / top * 100:.0f}%")), style=BAR_TRACK),
                Text(f"${value:,}", size="sm", style=AMOUNT),
                style=BAR_ROW,
            )
            for region, value in sorted(self.data.items(), key=lambda kv: -kv[1])
        ]
        return Card(h("ul", *rows, role="list", style=CHART_LIST), title="Revenue by region", style=CHART)

container_type="inline-size" makes the card a container; container={"compact": ...} hides the amounts when the card is narrow, whatever the size of the screen. That’s what makes a component reusable in any layout.

4. The page

@router.page("/")
class Overview(Page):
    title = "Dashboard · Rational Web"
    days = State("30")
    seed = State(0)

    def set_range(self, value: str):
        if value in dict(RANGE_OPTIONS):  # never trust the browser: ignore values that aren't options
            self.days = value

    def refresh(self):
        self.seed += 1

    def render(self):
        m = self.use(MetricsService).overview(int(self.days), self.seed)
        return Row(
            Sidebar(),
            Main(
                Row(
                    Column(Heading("Overview", level=1), Text("Sales performance at a glance", muted=True), gap="xs"),
                    Spacer(),
                    Select("Range", RANGE_OPTIONS, value=self.days, on_change=self.set_range, hide_label=True),
                    Button("Refresh", variant="secondary", on_click=self.refresh),
                    wrap=True,
                    align="end",
                ),
                # As many columns as fit, at least 200px wide each: responsive without media queries.
                Grid(
                    StatCard(label="Revenue", value=f"${m.revenue:,}", delta=12.4),
                    StatCard(label="Orders", value=f"{m.orders:,}", delta=4.1),
                    StatCard(label="Conversion", value=f"{m.conversion}%", delta=-0.6),
                    StatCard(label="Refunds", value=str(m.refunds), delta=-2.3),
                    min_column_width=200,
                ),
                Grid(RegionChart(data=m.by_region), RecentOrders(orders=m.recent), min_column_width=340),
                style=MAIN,
            ),
            align="stretch",
            gap=0,
            collapse="narrow",  # the sidebar moves above the content below 1024px
        )
  • Grid(min_column_width=200) fits as many KPI tiles per row as the space allows.

  • Row(collapse="narrow") stacks the sidebar above the content on tablets and phones.

  • set_range ignores values that aren’t offered options: never trust the browser.