ui_storybook/components/shell/workspace_badge.rs
1//! `WorkspaceBadge` — top-of-rail workspace marker (M-UI.2 / AUT-122).
2//!
3//! Compact square tile with the active workspace's monogram. Includes a
4//! small chevron glyph that signals "click for the workspace switcher".
5//! Purely visual; the switcher menu is the parent's responsibility
6//! (UI-05).
7
8use leptos::prelude::*;
9
10/// View-model for the workspace badge at the top of the rail.
11#[derive(Debug, Clone, PartialEq, Eq)]
12pub struct WorkspaceBadgeView {
13 /// Stable id (matches the workspace fixture's id).
14 pub id: &'static str,
15 /// 2-letter monogram displayed inside the tile.
16 pub monogram: &'static str,
17 /// Workspace label, used for the accessible title.
18 pub label: &'static str,
19 /// Optional accent color for the tile background (CSS-color
20 /// string). Defaults to the brand red when `None`.
21 pub accent: Option<&'static str>,
22}
23
24#[component]
25pub fn WorkspaceBadge(
26 view: WorkspaceBadgeView,
27 /// `true` when the workspace-switcher popover is open. Adds a
28 /// `workspace-badge-open` class for the parent menu's open state.
29 #[prop(optional)]
30 open: bool,
31) -> impl IntoView {
32 let style = view
33 .accent
34 .map(|a| format!("background:{a}"))
35 .unwrap_or_default();
36 let class = if open {
37 "workspace-badge workspace-badge-open"
38 } else {
39 "workspace-badge"
40 };
41 view! {
42 <button class=class title=view.label aria-haspopup="menu" aria-expanded=open>
43 <span class="workspace-badge-tile" style=style>{view.monogram}</span>
44 <span class="workspace-badge-chevron" aria-hidden="true">"▾"</span>
45 </button>
46 }
47}