diff --git a/crates/ui2/src/components.rs b/crates/ui2/src/components.rs index 4d7e3c14b6..46d8a59804 100644 --- a/crates/ui2/src/components.rs +++ b/crates/ui2/src/components.rs @@ -10,6 +10,7 @@ mod input; mod keybinding; mod label; mod list; +mod popover; mod slot; mod stack; mod stories; @@ -28,6 +29,7 @@ pub use input::*; pub use keybinding::*; pub use label::*; pub use list::*; +pub use popover::*; pub use slot::*; pub use stack::*; pub use stories::*; diff --git a/crates/ui2/src/components/popover.rs b/crates/ui2/src/components/popover.rs new file mode 100644 index 0000000000..74478e4051 --- /dev/null +++ b/crates/ui2/src/components/popover.rs @@ -0,0 +1,52 @@ +use gpui::{ + AnyElement, Component, Div, ElementId, ParentElement, RenderOnce, Styled, WindowContext, +}; +use smallvec::SmallVec; + +use crate::{v_stack, StyledExt}; + +#[derive(RenderOnce)] +pub struct Popover { + children: SmallVec<[AnyElement; 2]>, + aside: Option>, +} + +impl Component for Popover { + type Rendered = Div; + + fn render(self, cx: &mut WindowContext) -> Self::Rendered { + v_stack() + .relative() + .elevation_2(cx) + .p_1() + .children(self.children) + .when_some(self.aside, |this, aside| { + // TODO: This will statically position the aside to the top right of the popover. + // We should update this to avoid collisions with the window edges. + this.child( + v_stack() + .top_0() + .neg_right_1() + .absolute() + .elevation_2(cx) + .p_1() + .children(aside), + ) + }) + } +} + +impl Popover { + pub fn new() -> Self { + Self { + children: SmallVec::new(), + aside: None, + } + } +} + +impl ParentElement for Popover { + fn children_mut(&mut self) -> &mut SmallVec<[AnyElement; 2]> { + &mut self.children + } +}