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,
};
#[derive(Debug, Clone)]
enum Message {
NavigationAction(NavigationAction<Page>),
}
impl NavigationConvertible for Message {
type PageMapper = Page;
fn from_action(action: NavigationAction<Self::PageMapper>) -> Self {
Self::NavigationAction(action)
}
}
#[derive(Debug, Hash, Eq, PartialEq, Clone)]
enum Page {
LoginPage,
HomePage(String),
}
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>> {
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> {
if let Message::NavigationAction(action) = &message {
return self.nav.handle_actions(action.clone());
}
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,
};
#[derive(Debug, Clone)]
enum Message {
NavigationAction(NavigationAction<Page>),
}
impl NavigationConvertible for Message {
type PageMapper = Page;
fn from_action(action: NavigationAction<Self::PageMapper>) -> Self {
Self::NavigationAction(action)
}
}
#[derive(Debug, Hash, Eq, PartialEq, Clone)]
enum Page {
SettingsPage,
HomePage,
}
impl TabsNavigatorMapper for Page {
type Message = Message;
fn into_component(&self) -> Box<dyn PageComponent<Self::Message>> {
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> {
if let Message::NavigationAction(action) = &message {
return self.nav.handle_actions(action.clone());
}
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,
};
#[derive(Debug, Clone)]
enum Message {
NavigationAction(NavigationAction<Page>),
}
impl NavigationConvertible for Message {
type PageMapper = Page;
fn from_action(action: NavigationAction<Self::PageMapper>) -> Self {
Self::NavigationAction(action)
}
}
#[derive(Debug, Hash, Eq, PartialEq, Clone)]
enum Page {
SettingsPage,
HomePage,
}
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>> {
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> {
if let Message::NavigationAction(action) = &message {
return self.nav.handle_actions(action.clone());
}
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.