Conversation Sidebar
The conversation sidebar adds an icon tab strip and expandable panel to /messaging/:contact_id. You can view and edit contact details, notes, activity history, and todos alongside the active conversation.
Layout
Section titled “Layout”The conversation view uses a three-section layout:
| Section | Width | Content |
|---|---|---|
| Contact list | 25% | Searchable contact sidebar |
| Feed | flex-1 | Messages + calls timeline |
| Sidebar | 40px icon strip + 320px panel | Contact info, notes, activity, todos |
The panel only renders when a tab is active. When closed, only the 40px icon strip is visible and the feed expands to fill the space.
SidebarTab Enum
Section titled “SidebarTab Enum”#[derive(Debug, Clone, Copy, PartialEq, Eq)]pub enum SidebarTab { ContactInfo, // Editable contact details Notes, // Contact notes Activity, // Call/note/todo timeline Todos, // Contact todos}State is managed in MessagingContactView as a Signal<Option<SidebarTab>>. None means the panel is closed.
Icon Strip
Section titled “Icon Strip”The strip renders four buttons vertically, each mapped to a SidebarTab:
| Icon | Tab | Component Rendered |
|---|---|---|
User | ContactInfo | ContactSidebar |
StickyNote | Notes | ContactRightPanel (notes tab) |
History | Activity | ContactRightPanel (activity tab) |
ListTodo | Todos | ContactRightPanel (todos tab) |
Clicking an active tab closes the panel. Clicking an inactive tab switches to it.
onclick: move |_| { if active_tab() == Some(sidebar_tab) { active_tab.set(None); } else { active_tab.set(Some(sidebar_tab)); }}Key-Based Remounting
Section titled “Key-Based Remounting”ContactRightPanel uses Dioxus Tabs internally, which only reads default_value on mount. To switch between Notes, Activity, and Todos correctly, the sidebar sets a key prop that forces a full remount:
ContactRightPanel { key: "{inner_tab}", default_tab: inner_tab.to_string(), // ...}Without this, switching from Notes → Activity would keep Notes visible because Tabs ignores default_value changes after mount.
ConversationSidebarPanel Component
Section titled “ConversationSidebarPanel Component”File: src/mods/messaging/components/conversation_sidebar_component.rs
This component accepts the active_tab signal and all props needed by both ContactSidebar and ContactRightPanel. It renders the icon strip unconditionally and the panel content conditionally based on the active tab.
ContactInfo tab renders ContactSidebar with full contact CRUD — edit fields, manage phones, emails, addresses, tags, and user assignments.
Notes/Activity/Todos tabs render ContactRightPanel with the appropriate default_tab value.
Data Loading
Section titled “Data Loading”MessagingContactView loads eight resources in parallel on mount:
| Resource | API Call |
|---|---|
contact_resource | get_contact_api(id) |
calls_resource | get_contact_calls_api(id) |
messages_resource | get_contact_messages_api(uuid) |
phones_resource | get_phones_api() |
notes_resource | get_contact_notes_api(id) |
todos_resource | get_contact_todos_api(id) |
tags_resource | get_contact_tags_api() |
org_members_resource | get_org_members_api() |
Every mutation (save, delete, create) triggers a resource restart to refresh data.
Save Status
Section titled “Save Status”Contact edits in the sidebar follow a status state machine:
Idle → Saving → Saved → (2s delay) → Idle ↘ Error("message")The SaveStatus enum drives UI indicators so the user sees feedback during save operations.
Adding a New Tab
Section titled “Adding a New Tab”- Add a variant to
SidebarTabinsidebar_tab_type.rs - Add the icon and label to the
tabsarray inConversationSidebarPanel - Add icon rendering in the match block
- Add panel content rendering for the new tab
Key Files
Section titled “Key Files”| File | Purpose |
|---|---|
src/mods/messaging/types/sidebar_tab_type.rs | SidebarTab enum |
src/mods/messaging/components/conversation_sidebar_component.rs | Sidebar panel + icon strip |
src/mods/messaging/views/messaging_contact_view.rs | Parent view with state + handlers |
src/mods/contact/components/contact_right_panel_component.rs | Notes/activity/todos panel (added default_tab prop) |