snora_core/sidebar.rs
1//! Vertical navigation rail (icon-only sidebar).
2//!
3//! A [`SideBar`] is a pure data contract describing a strip of
4//! icon-and-tooltip buttons plus the currently active one. The engine
5//! renders it, and pressing a button emits the item's `on_press` message.
6//!
7//! This is the minimum-viable navigation affordance. If your app needs
8//! collapsible groups or nested navigation, compose your own element and
9//! put it in the `side_bar` slot of [`crate::AppLayout`] directly —
10//! snora-core does not force you through [`SideBar`].
11
12use crate::icon::Icon;
13
14/// One entry in a sidebar.
15///
16/// `ViewId` is the application's enum of addressable views. The sidebar
17/// highlights the item whose `view_id` equals [`SideBar::active`].
18#[derive(Debug, Clone)]
19pub struct SideBarItem<Message, ViewId>
20where
21 Message: Clone,
22 ViewId: Clone + PartialEq,
23{
24 /// The view this item points to. Compared against [`SideBar::active`]
25 /// to decide whether to apply the highlight.
26 pub view_id: ViewId,
27 /// Visual icon for the rail button.
28 pub icon: Icon,
29 /// Tooltip shown on hover. Required for accessibility — keyboard and
30 /// screen-reader users rely on it.
31 pub tooltip: String,
32 /// Message emitted when the user activates this item.
33 pub on_press: Message,
34}
35
36/// The vertical navigation rail as a whole.
37#[derive(Debug, Clone)]
38pub struct SideBar<Message, ViewId>
39where
40 Message: Clone,
41 ViewId: Clone + PartialEq,
42{
43 /// The list of rail entries, in display order.
44 pub items: Vec<SideBarItem<Message, ViewId>>,
45 /// The id of the view that is currently displayed in the body slot.
46 /// The engine uses this to apply an "active" visual treatment.
47 pub active: ViewId,
48}