chore: audit all components (#2)
Reviewed-on: #2
This commit was merged in pull request #2.
This commit is contained in:
+100
-16
@@ -1,13 +1,17 @@
|
||||
use gpui::AppContext as _;
|
||||
use gpui::{
|
||||
AnyView, App, Context, Entity, IntoElement, ParentElement as _, Render, SharedString,
|
||||
Styled as _, Window, div, px,
|
||||
AnyView, App, Bounds, Context, ElementId, Entity, InteractiveElement as _, IntoElement,
|
||||
ParentElement as _, Pixels, Render, SharedString, Styled as _, Window, canvas, div, point, px,
|
||||
};
|
||||
use gpui_native_theme::ActiveTheme as _;
|
||||
use gpui_native_theme::{ActiveTheme as _, BORDER_WIDTH};
|
||||
use gpui_native_utils::{anchor_bounds, record_anchor_bounds};
|
||||
|
||||
const PANEL_BOUNDS_ID: &str = "tooltip-panel-bounds";
|
||||
|
||||
/// A small text panel gpui shows next to a hovered element.
|
||||
pub struct Tooltip {
|
||||
text: SharedString,
|
||||
anchor: Option<Bounds<Pixels>>,
|
||||
}
|
||||
|
||||
impl Tooltip {
|
||||
@@ -16,7 +20,28 @@ impl Tooltip {
|
||||
where
|
||||
L: Into<SharedString>,
|
||||
{
|
||||
cx.new(|_| Self { text: text.into() })
|
||||
cx.new(|_| Self {
|
||||
text: text.into(),
|
||||
anchor: None,
|
||||
})
|
||||
}
|
||||
|
||||
/// Sets the anchor element ID for the tooltip.
|
||||
pub fn anchored<L, I>(text: L, anchor_id: I) -> impl Fn(&mut Window, &mut App) -> AnyView
|
||||
where
|
||||
L: Into<SharedString>,
|
||||
I: Into<ElementId>,
|
||||
{
|
||||
let text = text.into();
|
||||
let anchor_id = anchor_id.into();
|
||||
move |_window, cx| {
|
||||
let anchor = anchor_bounds(&anchor_id, cx);
|
||||
cx.new(|_| Self {
|
||||
text: text.clone(),
|
||||
anchor,
|
||||
})
|
||||
.into()
|
||||
}
|
||||
}
|
||||
|
||||
/// The `.tooltip(...)` closure for a plain text tooltip.
|
||||
@@ -30,20 +55,79 @@ impl Tooltip {
|
||||
}
|
||||
|
||||
impl Render for Tooltip {
|
||||
fn render(&mut self, _window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
|
||||
fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
|
||||
// Copied out: the mutable reads below need `cx` free of this borrow.
|
||||
let theme = cx.theme();
|
||||
let text_size = theme.sizes.small.text_size;
|
||||
let spacing_unit = theme.spacing.unit;
|
||||
let surface = theme.colors.surface;
|
||||
let surface_foreground = theme.colors.surface_foreground;
|
||||
let radius_sm = theme.radius.sm;
|
||||
let shadows = theme.elevations.popover.shadows();
|
||||
|
||||
div()
|
||||
.px_2()
|
||||
.py_1()
|
||||
.max_w(px(360.))
|
||||
.bg(theme.colors.surface)
|
||||
.border_1()
|
||||
.border_color(theme.colors.border)
|
||||
.rounded(theme.radius.sm)
|
||||
.text_size(text_size)
|
||||
.text_color(theme.colors.surface_foreground)
|
||||
.child(self.text.clone())
|
||||
let border = if theme.borders.overlays {
|
||||
theme.colors.border
|
||||
} else {
|
||||
theme.colors.surface
|
||||
};
|
||||
|
||||
let build_panel = || {
|
||||
div()
|
||||
.debug_selector(|| "tooltip-panel".to_string())
|
||||
.px_2()
|
||||
.py_1()
|
||||
.max_w(px(360.))
|
||||
.bg(surface)
|
||||
.border_1()
|
||||
.border_color(border)
|
||||
.rounded(radius_sm)
|
||||
.shadow(shadows.clone())
|
||||
.text_size(text_size)
|
||||
.text_color(surface_foreground)
|
||||
.child(self.text.clone())
|
||||
};
|
||||
|
||||
let (wrapper, panel) = match self.anchor {
|
||||
Some(parent) => {
|
||||
let origin = window.mouse_position() + point(px(1.), px(1.));
|
||||
let viewport_height = window.viewport_size().height;
|
||||
|
||||
let height = anchor_bounds(&ElementId::from(PANEL_BOUNDS_ID), cx)
|
||||
.map(|bounds| bounds.size.height)
|
||||
.unwrap_or_else(|| {
|
||||
text_size * 1.5 + window.rem_size() * 0.5 + BORDER_WIDTH * 2.0
|
||||
});
|
||||
|
||||
let below = viewport_height - spacing_unit - parent.bottom();
|
||||
let above = parent.top() - spacing_unit;
|
||||
let hang_below = below >= height || below >= above;
|
||||
|
||||
let panel = build_panel()
|
||||
.ml(parent.left() - origin.x)
|
||||
.mt(if hang_below {
|
||||
parent.bottom() + spacing_unit - origin.y
|
||||
} else {
|
||||
parent.top() - spacing_unit - height - origin.y
|
||||
})
|
||||
.child(
|
||||
canvas(
|
||||
record_anchor_bounds(ElementId::from(PANEL_BOUNDS_ID)),
|
||||
|_, _, _, _| {},
|
||||
)
|
||||
.absolute()
|
||||
.inset_0(),
|
||||
);
|
||||
(div().debug_selector(|| "tooltip-anchor".to_string()), panel)
|
||||
}
|
||||
None => {
|
||||
let wrapper = div()
|
||||
.debug_selector(|| "tooltip-anchor".to_string())
|
||||
.pl(spacing_unit * 2.0)
|
||||
.pt(spacing_unit * 2.0);
|
||||
(wrapper, build_panel())
|
||||
}
|
||||
};
|
||||
|
||||
wrapper.child(panel)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user