T22: Collaboration

- presence: avatars ringed in each peer's color with where they are, press to
  follow; a breathing live dot; follow mode frames the view and stops on Escape
- remote cursors and selections painted over a field from its own layout
- comment threads with replies, reactions and resolve; a marker that opens a
  thread in a bubble; a sidebar of open and resolved threads
- annotations washed in their authors' colors, notes on hover
- suggestion mode: edits become suggestions word by word; track changes shows
  them struck and underlined, to accept or reject
- sharing: invite by email with checked chips, roles, the access list and who
  the link lets in, in one dialog
- primitives::hold_focus gives a mode its own focus, shared with ZenMode
- AvatarGroup's tuck and count shared; Avatar::ring_color; TagInput::check;
  TextInput::bounds_for_range; Popover::size
- icons: smile-plus, user-plus, message-square-diff
- gallery: the Collaboration page with scripted states
This commit is contained in:
ZacharyZhang-NY committed 2026-09-26 05:10:37 -04:00
1 parent 0623855f38
commit 153cf95b99
34 files changed
+3297 -86

No files matched your search

+9
View File
@@ -7,6 +7,7 @@ use crate::{
buttons::{Button, ButtonVariant},
forms::{float_height, surface},
primitives::{FocusScope, IconName, Takeover, give_back, take_focus},
theme::ControlSize,
};
type Content = Box<dyn FnOnce(&mut Window, &mut App) -> AnyElement>;
@@ -39,6 +40,7 @@ pub struct Popover {
label: SharedString,
icon: Option<IconName>,
variant: ButtonVariant,
size: ControlSize,
content: Content,
}
@@ -54,6 +56,7 @@ impl Popover {
label: label.into(),
icon: None,
variant: ButtonVariant::Secondary,
size: ControlSize::default(),
content: Box::new(move |window, cx| content(window, cx).into_any_element()),
}
}
@@ -68,6 +71,11 @@ impl Popover {
self.variant = variant;
self
}
pub fn size(mut self, size: ControlSize) -> Self {
self.size = size;
self
}
}
impl RenderOnce for Popover {
@@ -77,6 +85,7 @@ impl RenderOnce for Popover {
let toggle = state.clone();
let trigger = Button::new((self.id.clone(), "trigger"), self.label)
.variant(self.variant)
.size(self.size)
.when_some(self.icon, |button, icon| button.icon(icon))
.on_click(move |_, window, cx| {
if open {