Skip to main content

ui_storybook/fixtures/
workspaces.rs

1//! Workspace fixtures — list of workspaces the workspace switcher menu
2//! displays. Used by UI-05 (`WorkspaceSwitcherMenu`).
3
4use crate::components::shell::WorkspaceView;
5
6/// One workspace the user could switch to. Stays here as the small
7/// pre-UI-05 shape; `WorkspaceView` (used by `WorkspaceSwitcherMenu`)
8/// is the richer view-model with plan badge + member count + color.
9#[derive(Debug, Clone, PartialEq, Eq)]
10pub struct WorkspaceFixture {
11    /// Stable id.
12    pub id: &'static str,
13    /// Human label.
14    pub label: &'static str,
15    /// Two-letter avatar / monogram shown when the workspace has no icon.
16    pub monogram: &'static str,
17    /// `true` when this workspace is the currently-active one.
18    pub active: bool,
19}
20
21/// `WorkspaceView`s used by UI-05's `WorkspaceSwitcherMenu` stories.
22#[must_use]
23pub fn sample_workspace_views() -> Vec<WorkspaceView> {
24    vec![
25        WorkspaceView {
26            id: "ws-northwind",
27            initials: "NS",
28            name: "Northwind Studio",
29            plan_badge: Some("Pro"),
30            member_count: 14,
31            color: Some("#ef4444"),
32        },
33        WorkspaceView {
34            id: "ws-personal",
35            initials: "PE",
36            name: "Personal",
37            plan_badge: Some("Free"),
38            member_count: 1,
39            color: Some("#0ea5e9"),
40        },
41        WorkspaceView {
42            id: "ws-acme",
43            initials: "AC",
44            name: "Acme Inc.",
45            plan_badge: Some("Team"),
46            member_count: 4,
47            color: Some("#a78bfa"),
48        },
49    ]
50}
51
52/// Workspace list with many entries (for the `many` story variant).
53#[must_use]
54pub fn sample_workspace_views_many() -> Vec<WorkspaceView> {
55    let mut out = sample_workspace_views();
56    out.extend([
57        WorkspaceView {
58            id: "ws-client-demos",
59            initials: "CD",
60            name: "Client demos",
61            plan_badge: Some("Team"),
62            member_count: 7,
63            color: Some("#10b981"),
64        },
65        WorkspaceView {
66            id: "ws-onboarding",
67            initials: "ON",
68            name: "Onboarding",
69            plan_badge: Some("Free"),
70            member_count: 1,
71            color: Some("#f59e0b"),
72        },
73        WorkspaceView {
74            id: "ws-acquired",
75            initials: "AQ",
76            name: "Acquired Brands",
77            plan_badge: Some("Team"),
78            member_count: 21,
79            color: Some("#ec4899"),
80        },
81    ]);
82    out
83}
84
85/// Workspace with a very long name for the long-names truncation story.
86#[must_use]
87pub fn sample_workspace_views_long_names() -> Vec<WorkspaceView> {
88    vec![
89        WorkspaceView {
90            id: "ws-extremely-long",
91            initials: "VL",
92            name: "A very long workspace name that should truncate cleanly in the row",
93            plan_badge: Some("Team"),
94            member_count: 12,
95            color: Some("#ef4444"),
96        },
97        WorkspaceView {
98            id: "ws-also-long",
99            initials: "AL",
100            name: "Another long workspace name with more words",
101            plan_badge: Some("Pro"),
102            member_count: 2,
103            color: Some("#a78bfa"),
104        },
105    ]
106}
107
108/// Sample workspace list for the switcher.
109#[must_use]
110pub fn sample_workspaces() -> Vec<WorkspaceFixture> {
111    vec![
112        WorkspaceFixture {
113            id: "ws-personal",
114            label: "Personal",
115            monogram: "PE",
116            active: true,
117        },
118        WorkspaceFixture {
119            id: "ws-acme",
120            label: "Acme Inc.",
121            monogram: "AC",
122            active: false,
123        },
124        WorkspaceFixture {
125            id: "ws-client",
126            label: "Client demos",
127            monogram: "CD",
128            active: false,
129        },
130    ]
131}
132
133#[cfg(test)]
134mod tests {
135    use super::*;
136
137    #[test]
138    fn sample_has_exactly_one_active() {
139        let actives = sample_workspaces().into_iter().filter(|w| w.active).count();
140        assert_eq!(actives, 1, "exactly one workspace must be active");
141    }
142}