Skip to content

Widgets Navigation

mike-ward edited this page Jun 14, 2026 · 2 revisions

Navigation Widgets

Navigation widgets give users structural orientation — where they are, how to move between sections, and how to invoke commands.


Breadcrumb

gui.Breadcrumb(gui.BreadcrumbCfg{...}) renders a navigational trail of clickable segments. The last item is typically the current location and rendered non-clickably.

gui.Breadcrumb(gui.BreadcrumbCfg{
    ID: "nav",
    Items: []gui.BreadcrumbItemCfg{
        gui.NewBreadcrumbItem("home", "Home", nil),
        gui.NewBreadcrumbItem("docs", "Docs", nil),
        gui.NewBreadcrumbItem("api",  "API Reference", nil),
    },
    Selected: app.BreadcrumbSelected,
    OnSelect: func(id string, _ *gui.Event, w *gui.Window) {
        gui.State[App](w).BreadcrumbSelected = id
    },
})

TabControl

gui.TabControl(gui.TabControlCfg{...}) renders a row of tabs above a content panel. Tabs are keyboard-accessible and can be made reorderable by drag-and-drop.

gui.TabControl(gui.TabControlCfg{
    ID:      "main-tabs",
    IDFocus: 10,
    Sizing:  gui.FillFit,
    Items: []gui.TabItemCfg{
        gui.NewTabItem("overview", "Overview", []gui.View{
            gui.Text(gui.TextCfg{Text: "Overview content"}),
        }),
        gui.NewTabItem("settings", "Settings", []gui.View{
            gui.Text(gui.TextCfg{Text: "Settings content"}),
        }),
    },
    Selected: app.ActiveTab,
    OnSelect: func(id string, _ *gui.Event, w *gui.Window) {
        gui.State[App](w).ActiveTab = id
    },
})

To allow drag-to-reorder:

gui.TabControl(gui.TabControlCfg{
    // ...
    Reorderable: true,
    OnReorder: func(movedID, beforeID string, w *gui.Window) {
        a := gui.State[App](w)
        from, to := gui.ReorderIndices(tabIDs(a.Tabs), movedID, beforeID)
        if from >= 0 {
            sliceMove(&a.Tabs, from, to)
        }
    },
})

Menubar

gui.Menubar(w, gui.MenubarCfg{...}) renders an application menu bar. Each entry is a Menu with nested MenuItem values.

gui.Menubar(w, gui.MenubarCfg{
    Menus: []gui.MenuCfg{
        {
            Label: "File",
            Items: []gui.MenuItemCfg{
                {Label: "New",  KeyCmd: "Ctrl+N", OnClick: onNew},
                {Label: "Open", KeyCmd: "Ctrl+O", OnClick: onOpen},
                {Separator: true},
                {Label: "Quit", KeyCmd: "Ctrl+Q", OnClick: onQuit},
            },
        },
        {
            Label: "Edit",
            Items: []gui.MenuItemCfg{
                {Label: "Cut",   KeyCmd: "Ctrl+X", OnClick: onCut},
                {Label: "Copy",  KeyCmd: "Ctrl+C", OnClick: onCopy},
                {Label: "Paste", KeyCmd: "Ctrl+V", OnClick: onPaste},
            },
        },
    },
})

Items can be nested: set SubItems on a MenuItemCfg to create a submenu.


ContextMenu

gui.ContextMenu(w, gui.ContextMenuCfg{...}) wraps any view and attaches a right-click menu to it.

gui.ContextMenu(w, gui.ContextMenuCfg{
    ID: "row-ctx",
    Items: []gui.MenuItemCfg{
        {Label: "Edit",   OnClick: onEdit},
        {Label: "Delete", OnClick: onDelete},
    },
    Content: []gui.View{
        rowView,
    },
})

Sidebar

w.Sidebar(gui.SidebarCfg{...}) is an animated slide-out panel — the equivalent of a navigation drawer. It is controlled by an Open bool field in your state.

gui.Row(gui.ContainerCfg{
    Sizing:  gui.FillFixed,
    Height:  400,
    Padding: gui.NoPadding,
    Content: []gui.View{
        w.Sidebar(gui.SidebarCfg{
            ID:    "nav-sidebar",
            Open:  app.SidebarOpen,
            Width: 220,
            Content: []gui.View{
                gui.Text(gui.TextCfg{Text: "Navigation"}),
                // nav items...
            },
        }),
        gui.Column(gui.ContainerCfg{
            Sizing:  gui.FillFill,
            Content: []gui.View{mainContent},
        }),
    },
})

Toggle the sidebar by flipping app.SidebarOpen in an OnClick callback; the animation runs automatically.


CommandPalette

gui.CommandPalette(gui.CommandPaletteCfg{...}) opens a fuzzy-search palette over the registered command registry. It integrates with go-gui's keyboard command system (see Advanced) and is typically triggered via a keyboard shortcut.

gui.CommandPalette(gui.CommandPaletteCfg{
    ID:       "palette",
    IDFocus:  999,
    Commands: app.Commands,
    OnSelect: func(cmd gui.Command, w *gui.Window) {
        cmd.Execute(w)
    },
})

Menu

gui.Menu(gui.MenuCfg{...}) renders a standalone popup menu. It contains MenuItem children and can be shown programmatically or attached to a right-click trigger via ContextMenu.

gui.Menu(gui.MenuCfg{
    ID: "file-menu",
    Items: []gui.MenuItemCfg{
        {Text: "New",    Shortcut: "Ctrl+N", OnClick: onNew},
        {Text: "Open",   Shortcut: "Ctrl+O", OnClick: onOpen},
        gui.MenuDivider(""),
        {Text: "Exit",   Shortcut: "Ctrl+Q", OnClick: onExit},
    },
})

MenuItem supports keyboard shortcuts, icons, checked state, submenus, and disable/enable conditions via CanExecute. MenuDivider inserts a separator line between groups of items.

For native OS menus, see Menubar and the native menu backend (gui/backend/nativemenu/). For right-click convenience, see ContextMenu.

Clone this wiki locally