{}

Navigation patterns

Navigation in BESPA is three layered widgets: a strip across the top, a rail or drawer down the side, and the in-page back-link conventions that let any page return to where the user came from. The framework adapts between rail and drawer based on viewport width.

The main menu

Most apps define their menu once in a shared helper and reuse it on every page. The pattern from this website’s shared/nav.go:

func navMenu() *nav.MainMenuWidget {
    rail := wf.NavRail().AddTop(
        wf.NavTarget("Home", "/").WithIcon("home"),
        wf.NavTarget("Orders", "/orders").WithIcon("receipt").WithBadge("3"),
        wf.NavTarget("Reports", "/reports").WithIcon("bar chart"),
    ).AddBottom(
        wf.NavTarget("Profile", "/profile").WithIcon("person"),
    )

    drawer := wf.NavDrawer().AddTop(
        // same targets, full-width labels
    )

    return wf.MainMenu().WithRail(rail).WithVertical(drawer)
}

Targets and decorations

NavTarget(label, path) is the link. Common chained options:

Sub-menus

For sections with their own internal navigation, attach a sub-drawer. Open the section to replace the main menu with the section’s targets, plus a NavTargetBack breadcrumb back to the parent:

wf.NavTarget("Reports", "/reports/overview").
    WithIcon("bar chart").
    WithSubMenu(wf.NavDrawer().AddTop(
        wf.NavTargetBack("Main menu"),
        wf.Rule(),
        wf.NavTarget("Daily", "/reports/daily").WithIcon("today"),
        wf.NavTarget("Weekly", "/reports/weekly").WithIcon("date range"),
        wf.NavTarget("Custom range", "/reports/custom").WithIcon("date range"),
    ))

This site’s Learn section is exactly this pattern — try clicking “Learn” in the side menu and you’ll see the sub-drawer slide in.

Back-link plumbing

BESPA uses the _back state variable to remember where a user came from. Pages that open from a list view (“Edit” links, detail views) should set it; the destination uses WithHrefBack or RedirectBack to return cleanly:

// Default back button — uses state._back set by the caller.
wf.ButtonText("").Add("Back").WithHrefBack(),

// Explicit destination:
wf.ButtonText("").Add("Back").WithHref("/orders"),

// Add _back to a link so the destination has a return path:
wf.Link("/orders/123?_back=" + url.QueryEscape("/orders")).Add("Open"),

When you call WithHrefBack without an explicit back URL, the button falls back to history.go(-1) if it can detect that there’s history to walk; otherwise it’s hidden automatically.

See also

Showcase → Navigation widgets — all three flavors side by side.

Basics → Targeting frames — when a click should target a nested page rather than the top.