Navigation Controls
List, MenuBar, Toolbar, and SideMenu — the building blocks for structured navigation in any Malena application.
Navigation Components
| Class | Purpose |
|---|---|
ml::List | Vertically stacked rows with optional dividers, start/end slots, and nesting |
ml::MenuBar | Desktop-style horizontal menu bar with dropdown panels and submenus |
ml::Toolbar | Horizontal/vertical strip of buttons, separators, and embedded components |
ml::SideMenu | Slide-in panel anchored to an edge, with overlay or push modes |
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.
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);
// 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();
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.
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);
// 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();