ml::docs | Your First App Manifests Events Messaging Plugins Scenes Resources
See all tutorials →
Intermediate 5 sections ~25 min C++17/20

Navigation Controls

List, MenuBar, Toolbar, and SideMenu — the building blocks for structured navigation in any Malena application.

interactive preview — click the menus and toolbar buttons
File
New Ctrl+N
Open Ctrl+O
Save Ctrl+S
Edit
Undo Ctrl+Z
Redo Ctrl+Y
✓ Word wrap
View
Zoom in
Zoom out
New
Open
Save
Undo
Redo
Search…
Wi-Fi
Connected to "HomeNet"
Bluetooth
Pair devices wirelessly
Off
Dark mode
On ●
Introduction

Navigation Components

ClassPurpose
ml::ListVertically stacked rows with optional dividers, start/end slots, and nesting
ml::MenuBarDesktop-style horizontal menu bar with dropdown panels and submenus
ml::ToolbarHorizontal/vertical strip of buttons, separators, and embedded components
ml::SideMenuSlide-in panel anchored to an edge, with overlay or push modes

1Navigation

List

A vertically stacked list container. Rows created via addItem() are owned by the list as ListItem objects and receive automatic styling updates. Rows added via add() are non-owned — the list positions them but does not restyle or resize them.

ListItem supports a primary label, an optional description line, and two slots (start and end) that accept any ml::Core component — icons, toggles, badges, etc.

List — building a settings panel cpp
ml::List settings;
settings.setWidth(400.f);
settings.setPosition({40.f, 100.f});

// Label-only row
settings.addItem("Wi-Fi");

// Label + description row
settings.addItem("Bluetooth", "Pair devices wirelessly");

// Row with an end-slot toggle
ml::PillToggle darkMode;
auto& item = settings.addItem("Dark mode");
item.setEnd(darkMode);

// Row with start icon and end toggle
ml::PillToggle wifiToggle;
auto& wifi = settings.addItem("Wi-Fi");
wifi.setEnd(wifiToggle);

addComponent(settings);
List — custom rows and nesting cpp
// Any ml::Core can be used as a row (non-owned)
ml::Rectangle sectionHeader;
sectionHeader.setFillColor(sf::Color(30, 30, 50));
settings.add(sectionHeader);

// Nested list — the sub-list is added as a non-owned row
ml::List sub;
sub.setWidth(settings.getWidth());
sub.addItem("Option A");
sub.addItem("Option B");
settings.add(sub);
addComponent(sub);  // register sub separately so its items receive events

// Query
std::size_t rows = settings.rowCount();
float h = settings.getTotalHeight();
settings.clear();


3Navigation

Toolbar

A horizontal or vertical strip of buttons and separators. Buttons created via addButton() are owned by the toolbar and receive hover highlighting automatically. External components added via add() are not owned — register them with addComponent() separately so their events fire.

Toolbar — typical setup below a MenuBar cpp
ml::Toolbar toolbar;
toolbar.setPosition({0.f, 30.f}); // below a MenuBar

toolbar.addButton("New",  [&]{ newFile();  });
toolbar.addButton("Open", [&]{ openFile(); });
toolbar.addButton("Save", [&]{ save();     });
toolbar.addSeparator();
toolbar.addButton("Undo", [&]{ undo(); });
toolbar.addButton("Redo", [&]{ redo(); });
toolbar.addSeparator();

// Embed any component — it must be registered separately
ml::TextInput search;
search.setSize({200.f, 28.f});
search.setPlaceholder("Search...");
toolbar.add(search);
addComponent(search);   // register search with the scene

addComponent(toolbar);
Toolbar — sizing and orientation cpp
// By default the toolbar fills the window width.
// Override the bar length explicitly:
toolbar.setBarLength(600.f);
float len = toolbar.getBarLength();
float thickness = toolbar.getBarThickness(); // height (H) or width (V)

// Vertical toolbar (placed on the left edge)
ml::Toolbar vbar(ml::ToolbarSettings::Orientation::VERTICAL);
vbar.setPosition({0.f, 60.f}); // below a horizontal toolbar

// Clear all items
toolbar.clear();
std::size_t n = toolbar.itemCount();

4Navigation

SideMenu

A panel that slides in from the left or right edge of the window, triggered by a built-in hamburger button. Two display modes are available: OVERLAY (slides over content) and PUSH (fires open/close callbacks so your layout can shift). The panel draws and positions its content internally — no separate addComponent() call needed for the content.

SideMenu — overlay mode (default) cpp
ml::SideMenu menu;
menu.setPanelWidth(280.f);

auto& list = menu.getList();
list.addItem("Home");
list.addItem("Settings");
list.addItem("Profile");
list.addItem("Help");

addComponent(menu); // handles hamburger, backdrop, and panel
SideMenu — push mode cpp
ml::SideMenu menu(ml::SideMenuSettings::Mode::PUSH,
                  ml::SideMenuSettings::Anchor::LEFT);
menu.setPanelWidth(280.f);

// Shift main content when the menu opens/closes
menu.onOpen([&]  { mainContent.setPosition({menu.getPanelWidth(), 0.f}); });
menu.onClose([&] { mainContent.setPosition({0.f, 0.f}); });

addComponent(menu);
SideMenu — custom content and programmatic control cpp
// Replace the built-in List with any ml::Core component
menu.setContent(myCustomPanel);

// Open / close / toggle programmatically
menu.open();
menu.close();
menu.toggle();
bool open = menu.isOpen();

// Reposition the hamburger button
menu.setHamburgerPosition({12.f, 12.f});