Add hover behaviour to tabs

Co-Authored-By: Marshall <marshall@zed.dev>
Co-Authored-By: Nathan <nathan@zed.dev>
This commit is contained in:
Conrad Irwin 2023-11-03 10:54:26 -06:00
parent d3b02c4de4
commit c604a2e34e
6 changed files with 71 additions and 5 deletions

View file

@ -212,6 +212,19 @@ pub trait Component<V> {
{
self.map(|this| if condition { then(this) } else { this })
}
fn when_some<T>(self, option: Option<T>, then: impl FnOnce(Self, T) -> Self) -> Self
where
Self: Sized,
{
self.map(|this| {
if let Some(value) = option {
then(this, value)
} else {
this
}
})
}
}
impl<V> Component<V> for AnyElement<V> {

View file

@ -3,7 +3,7 @@ use crate::{
ElementInteraction, FocusDisabled, FocusEnabled, FocusHandle, FocusListeners, Focusable,
GlobalElementId, GroupBounds, InteractiveElementState, LayoutId, Overflow, ParentElement,
Pixels, Point, SharedString, StatefulInteraction, StatefulInteractive, StatelessInteraction,
StatelessInteractive, Style, StyleRefinement, Styled, ViewContext,
StatelessInteractive, Style, StyleRefinement, Styled, ViewContext, Visibility,
};
use refineable::Refineable;
use smallvec::SmallVec;
@ -249,11 +249,15 @@ where
cx: &mut ViewContext<V>,
) {
self.with_element_id(cx, |this, _global_id, cx| {
let style = this.compute_style(bounds, element_state, cx);
if style.visibility == Visibility::Hidden {
return;
}
if let Some(group) = this.group.clone() {
GroupBounds::push(group, bounds, cx);
}
let style = this.compute_style(bounds, element_state, cx);
let z_index = style.z_index.unwrap_or(0);
let mut child_min = point(Pixels::MAX, Pixels::MAX);

View file

@ -19,6 +19,9 @@ pub struct Style {
/// What layout strategy should be used?
pub display: Display,
/// Should the element be painted on screen?
pub visibility: Visibility,
// Overflow properties
/// How children overflowing their container should affect layout
#[refineable]
@ -107,6 +110,13 @@ impl Styled for StyleRefinement {
}
}
#[derive(Default, Clone, Copy, Debug, Eq, PartialEq)]
pub enum Visibility {
#[default]
Visible,
Hidden,
}
#[derive(Clone, Debug)]
pub struct BoxShadow {
pub color: Hsla,
@ -297,6 +307,7 @@ impl Default for Style {
fn default() -> Self {
Style {
display: Display::Block,
visibility: Visibility::Visible,
overflow: Point {
x: Overflow::Visible,
y: Overflow::Visible,

View file

@ -1,6 +1,7 @@
use crate::{
self as gpui2, hsla, point, px, relative, rems, AlignItems, DefiniteLength, Display, Fill,
FlexDirection, Hsla, JustifyContent, Length, Position, Rems, SharedString, StyleRefinement,
Visibility,
};
use crate::{BoxShadow, TextStyleRefinement};
use smallvec::smallvec;
@ -60,6 +61,26 @@ pub trait Styled {
self
}
/// Sets the visibility of the element to `visible`.
/// [Docs](https://tailwindcss.com/docs/visibility)
fn visible(mut self) -> Self
where
Self: Sized,
{
self.style().visibility = Some(Visibility::Visible);
self
}
/// Sets the visibility of the element to `hidden`.
/// [Docs](https://tailwindcss.com/docs/visibility)
fn invisible(mut self) -> Self
where
Self: Sized,
{
self.style().visibility = Some(Visibility::Hidden);
self
}
/// Sets the flex direction of the element to `column`.
/// [Docs](https://tailwindcss.com/docs/flex-direction#column)
fn flex_col(mut self) -> Self

View file

@ -159,6 +159,7 @@ impl Icon {
pub struct IconElement {
icon: Icon,
color: IconColor,
hover_color: Option<IconColor>,
size: IconSize,
}
@ -167,6 +168,7 @@ impl IconElement {
Self {
icon,
color: IconColor::default(),
hover_color: None,
size: IconSize::default(),
}
}
@ -176,13 +178,17 @@ impl IconElement {
self
}
pub fn hover_color(mut self, hover_color: impl Into<Option<IconColor>>) -> Self {
self.hover_color = hover_color.into();
self
}
pub fn size(mut self, size: IconSize) -> Self {
self.size = size;
self
}
fn render<V: 'static>(self, _view: &mut V, cx: &mut ViewContext<V>) -> impl Component<V> {
let fill = self.color.color(cx);
let svg_size = match self.size {
IconSize::Small => rems(0.75),
IconSize::Medium => rems(0.9375),
@ -192,7 +198,10 @@ impl IconElement {
.size(svg_size)
.flex_none()
.path(self.icon.path())
.text_color(fill)
.text_color(self.color.color(cx))
.when_some(self.hover_color, |this, hover_color| {
this.hover(|style| style.text_color(hover_color.color(cx)))
})
}
}

View file

@ -1361,9 +1361,16 @@ impl Pane {
let label = item.tab_content(Some(detail), cx);
let close_icon = || {
let id = item.id();
div()
.id(item.id())
.child(IconElement::new(Icon::Close).color(IconColor::Muted))
.invisible()
.group_hover("", |style| style.visible())
.child(
IconElement::new(Icon::Close)
.color(IconColor::Muted)
.hover_color(IconColor::Accent),
)
.on_click(move |pane: &mut Self, _, cx| {
pane.close_item_by_id(id, SaveIntent::Close, cx)
.detach_and_log_err(cx);
@ -1388,6 +1395,7 @@ impl Pane {
let close_right = ItemSettings::get_global(cx).close_position.right();
div()
.group("")
.id(item.id())
// .on_drag(move |pane, cx| pane.render_tab(ix, item.boxed_clone(), detail, cx))
// .drag_over::<DraggedTab>(|d| d.bg(cx.theme().colors().element_drop_target))