Skip to main content

ui_storybook/fixtures/
shell.rs

1//! Shell fixtures — nav rail items, workspace badge, user avatar
2//! (M-UI.2 / AUT-122).
3
4use crate::components::shell::{AppSection, NavItemView, UserAvatarView, WorkspaceBadgeView};
5
6/// Default nav rail items for Screen Studio.
7///
8/// `extra_count` adds a notification badge to the Library item so the
9/// `nav-rail-with-counts` story can demonstrate that variant without
10/// owning the variant logic inside the story body.
11#[must_use]
12pub fn sample_nav_items(extra_count: bool) -> Vec<NavItemView> {
13    vec![
14        NavItemView {
15            section: AppSection::Record,
16            label: "Record",
17            count: None,
18            disabled: false,
19        },
20        NavItemView {
21            section: AppSection::Library,
22            label: "Library",
23            count: if extra_count { Some(3) } else { None },
24            disabled: false,
25        },
26        NavItemView {
27            section: AppSection::Editor,
28            label: "Editor",
29            count: None,
30            disabled: false,
31        },
32        NavItemView {
33            section: AppSection::Cursor,
34            label: "Cursor",
35            count: None,
36            disabled: false,
37        },
38        NavItemView {
39            section: AppSection::Prefs,
40            label: "Prefs",
41            count: None,
42            disabled: false,
43        },
44    ]
45}
46
47/// Sample workspace badge.
48#[must_use]
49pub fn sample_workspace_badge() -> WorkspaceBadgeView {
50    WorkspaceBadgeView {
51        id: "ws-personal",
52        monogram: "PE",
53        label: "Personal",
54        accent: Some("#ef4444"),
55    }
56}
57
58/// Sample user avatar (monogram fallback, no image).
59#[must_use]
60pub fn sample_user_avatar() -> UserAvatarView {
61    UserAvatarView {
62        monogram: "M",
63        src: None,
64        name: "Matthew Harwood",
65    }
66}
67
68#[cfg(test)]
69mod tests {
70    use super::*;
71
72    #[test]
73    fn nav_items_have_one_per_section() {
74        let items = sample_nav_items(false);
75        assert_eq!(items.len(), 5);
76        let sections: Vec<_> = items.iter().map(|i| i.section).collect();
77        for section in [
78            AppSection::Record,
79            AppSection::Library,
80            AppSection::Editor,
81            AppSection::Cursor,
82            AppSection::Prefs,
83        ] {
84            assert!(sections.contains(&section), "missing section {section:?}");
85        }
86    }
87
88    #[test]
89    fn extra_count_adds_a_library_count_only() {
90        let plain = sample_nav_items(false);
91        let extra = sample_nav_items(true);
92        assert!(plain.iter().all(|i| i.count.is_none()));
93        let library_count = extra
94            .iter()
95            .find(|i| i.section == AppSection::Library)
96            .and_then(|i| i.count);
97        assert_eq!(library_count, Some(3));
98    }
99}