9 stable releases
| 1.6.0 | Dec 14, 2025 |
|---|---|
| 1.5.0 | Oct 4, 2025 |
| 1.4.1 | May 6, 2025 |
| 1.2.0 | Mar 3, 2025 |
| 1.1.0 | Feb 23, 2025 |
#606 in GUI
80KB
2K
SLoC
iced_navigation
iced_navigation is a navigation library for the iced GUI framework, designed to provide structured navigation patterns for building interactive applications.
| Stack navigation | Tab navigation | Drawer navigation |
|---|---|---|
Features
- Stack Navigator: Implements a stack-based navigation system.
- Tabs Navigator: Implements a tab-based navigation system.
- Drawer Navigator: Implements a drawer-based navigation system.
- Page Mapping: Define navigation pages and their corresponding components easily.
- Navigation Actions: Supports pushing, popping, and replacing pages dynamically.
Installation
To use iced_navigation, add it to your Cargo.toml:
[dependencies]
iced = "0.14"
iced_navigation = "1.6.0"
Usage
Example: Stack Navigator
use iced::{Element, Task};
use iced_navigation::{
stack_navigator::{StackNavigator, StackNavigatorMapper},
NavigationAction, NavigationConvertible, PageComponent,
};
// Defines the message enum used by the application
#[derive(Debug, Clone)]
enum Message {
NavigationAction(NavigationAction<Page>),
// Your aplication messages are defined here
}
impl NavigationConvertible for Message {
type PageMapper = Page;
// Maps navigation actions to your message enum
fn from_action(action: NavigationAction<Self::PageMapper>) -> Self {
Self::NavigationAction(action)
}
}
// This enum defines the pages available to the navigator
#[derive(Debug, Hash, Eq, PartialEq, Clone)]
enum Page {
LoginPage,
HomePage(String),
}
// This implementation maps pages to their titles and UI components
impl StackNavigatorMapper for Page {
type Message = Message;
fn title(&self) -> String {
match self {
Page::HomePage(_) => "Home page".to_owned(),
Page::LoginPage => "Login page".to_owned(),
}
}
fn into_component(&self) -> Box<dyn PageComponent<Self::Message>> {
// The page components must implement the PageComponent trait
match self {
Page::HomePage(name) => Box::new(HomeComponent::new(name.to_owned())),
Page::LoginPage => Box::new(LoginComponent::new()),
}
}
}
struct App {
nav: StackNavigator<Message, Page>,
}
impl App {
fn new() -> (Self, Task<Message>) {
let (nav, task) = StackNavigator::new(Page::LoginPage);
(Self { nav }, task)
}
fn update(&mut self, message: Message) -> Task<Message> {
// this ensures any navigation action is handled corretly by the navigator
if let Message::NavigationAction(action) = &message {
return self.nav.handle_actions(action.clone());
}
// the navigator will pass any message to the update function of the current page
self.nav.update(message)
}
fn view<'a>(&'a self) -> Element<'a, Message> {
self.nav.view()
}
}
fn main() -> iced::Result {
iced::application(App::new, App::update, App::view).run()
}
Example: Tabs Navigator
To use tab navigation, you must first enable the tabs feature in your Cargo.toml file:
[dependencies]
iced = "0.14"
iced_navigation = { version = "1.6.0", features = ["tabs"] }
use iced::{Element, Task};
use iced_navigation::{
tabs_navigator::{TabsNavigator, TabsNavigatorMapper},
NavigationAction, NavigationConvertible, PageComponent,
};
// Defines the message enum used by the application
#[derive(Debug, Clone)]
enum Message {
NavigationAction(NavigationAction<Page>),
// Your aplication messages are defined here
}
impl NavigationConvertible for Message {
type PageMapper = Page;
// Maps navigation actions to your message enum
fn from_action(action: NavigationAction<Self::PageMapper>) -> Self {
Self::NavigationAction(action)
}
}
// This enum defines the pages available to the navigator
#[derive(Debug, Hash, Eq, PartialEq, Clone)]
enum Page {
SettingsPage,
HomePage,
}
// This implementation maps pages to their titles and UI components
impl TabsNavigatorMapper for Page {
type Message = Message;
fn into_component(&self) -> Box<dyn PageComponent<Self::Message>> {
// The page components must implement the PageComponent trait
match self {
Page::HomePage => Box::new(HomeComponent::new()),
Page::SettingsPage => Box::new(SettingsComponent::new()),
}
}
}
struct App {
nav: TabsNavigator<Message, Page>,
}
impl App {
fn new() -> (Self, Task<Message>) {
let (nav, task) = TabsNavigator::new([Page::HomePage, Page::SettingsPage], Page::HomePage);
(Self { nav }, task)
}
fn update(&mut self, message: Message) -> Task<Message> {
// this ensures any navigation action is handled corretly by the navigator
if let Message::NavigationAction(action) = &message {
return self.nav.handle_actions(action.clone());
}
// the navigator will pass any message to the update function of the current page
self.nav.update(message)
}
fn view<'a>(&'a self) -> Element<'a, Message> {
self.nav.view()
}
}
fn main() -> iced::Result {
iced::application(App::new, App::update, App::view).run()
}
Example: Drawer Navigator
To use drawer navigation, you must first enable the drawer feature in your Cargo.toml file:
[dependencies]
iced = "0.14"
iced_navigation = { version = "1.6.0", features = ["drawer"] }
use iced::{Element, Task};
use iced_navigation::{
drawer_navigator::{DrawerNavigator, DrawerNavigatorMapper},
NavigationAction, NavigationConvertible, PageComponent,
};
// Defines the message enum used by the application
#[derive(Debug, Clone)]
enum Message {
NavigationAction(NavigationAction<Page>),
// Your aplication messages are defined here
}
impl NavigationConvertible for Message {
type PageMapper = Page;
// Maps navigation actions to your message enum
fn from_action(action: NavigationAction<Self::PageMapper>) -> Self {
Self::NavigationAction(action)
}
}
// This enum defines the pages available to the navigator
#[derive(Debug, Hash, Eq, PartialEq, Clone)]
enum Page {
SettingsPage,
HomePage,
}
// This implementation maps pages to their titles and UI components
impl DrawerNavigatorMapper for Page {
type Message = Message;
fn title(&self) -> String {
match self {
Page::HomePage => "Home page".to_owned(),
Page::SettingsPage => "Login page".to_owned(),
}
}
fn into_component(&self) -> Box<dyn PageComponent<Self::Message>> {
// The page components must implement the PageComponent trait
match self {
Page::HomePage => Box::new(HomeComponent::new()),
Page::SettingsPage => Box::new(SettingsComponent::new()),
}
}
}
struct App {
nav: DrawerNavigator<Message, Page>,
}
impl App {
fn new() -> (Self, Task<Message>) {
let (nav, task) =
DrawerNavigator::new([Page::HomePage, Page::SettingsPage], Page::HomePage);
(Self { nav }, task)
}
fn update(&mut self, message: Message) -> Task<Message> {
// this ensures any navigation action is handled corretly by the navigator
if let Message::NavigationAction(action) = &message {
return self.nav.handle_actions(action.clone());
}
// the navigator will pass any message to the update function of the current page
self.nav.update(message)
}
fn view<'a>(&'a self) -> Element<'a, Message> {
self.nav.view()
}
}
fn main() -> iced::Result {
iced::application(App::new, App::update, App::view).run()
}
Complete examples can be found in the examples folder.
Contributing
Contributions are welcome! Feel free to open issues and pull requests.
License
This project is licensed under the MIT License.
Dependencies
~41–63MB
~798K SLoC