Add hidden-on-hover sidebar mode
Domain ships HIDDEN_SIDEBAR_WIDTH_PX = 8 alongside the existing collapsed/default tiers. ElyShell tracks sidebar_hover_expanded with expand_hidden_sidebar / collapse_hidden_sidebar helpers; switching back to a non-hidden width via the layout cards or core API resets the flag automatically so the sidebar can never be both hidden and expanded after a mode change. Renderer: - render_sidebar takes a sidebar_hidden flag and routes to a thin 8 px clickable rail (hover bg + click expands) when the active space's width is at HIDDEN. - While the rail is expanded, render_browser overlays a transparent backdrop + the full default-width sidebar absolutely positioned in the shell inset, so the main pane content never reflows. - collapsed_sidebar_active still drives the COLLAPSED-tier compact sidebar; the hidden tier is opted out of that path. Appearance form: - Layout cards section gains the design's third "Hidden on hover" card with a 6 px sliver preview that mutates the active space to HIDDEN_SIDEBAR_WIDTH_PX. LayoutMode now derives id/width/preview from a small enum so adding a fourth mode would be one match arm. The hover-expanded state never persists into the domain; once the user switches modes or clicks the backdrop, it collapses cleanly.
This commit is contained in:
@@ -1,9 +1,9 @@
|
||||
use ely_browser_core::BrowserSnapshot;
|
||||
use ely_design_system::{colors, spacing};
|
||||
use ely_domain::BrowserTab;
|
||||
use ely_domain::{BrowserTab, DEFAULT_SIDEBAR_WIDTH_PX, HIDDEN_SIDEBAR_WIDTH_PX};
|
||||
use gpui::{
|
||||
AnyElement, Context, InteractiveElement, IntoElement, ParentElement, Render, Styled, Window,
|
||||
div, px, rgb, rgba,
|
||||
AnyElement, Context, InteractiveElement, IntoElement, ParentElement, Render, SharedString,
|
||||
StatefulInteractiveElement, Styled, Window, div, prelude::FluentBuilder, px, rgb, rgba,
|
||||
};
|
||||
|
||||
use super::chrome::{
|
||||
@@ -36,7 +36,9 @@ impl ElyShell {
|
||||
Ok(sidebar_width) => sidebar_width,
|
||||
Err(message) => return render_error(message),
|
||||
};
|
||||
let sidebar_collapsed = collapsed_sidebar_active(sidebar_width);
|
||||
let sidebar_hidden = sidebar_width <= f32::from(HIDDEN_SIDEBAR_WIDTH_PX);
|
||||
let sidebar_collapsed = collapsed_sidebar_active(sidebar_width) && !sidebar_hidden;
|
||||
let hover_expanded = sidebar_hidden && self.sidebar_hover_expanded;
|
||||
|
||||
div()
|
||||
.size_full()
|
||||
@@ -72,13 +74,52 @@ impl ElyShell {
|
||||
.p(px(spacing::SHELL_INSET))
|
||||
.gap(px(spacing::SIDEBAR_MAIN_GAP))
|
||||
.flex()
|
||||
.child(self.render_sidebar(&snapshot, sidebar_width, sidebar_collapsed, cx))
|
||||
.child(self.render_sidebar(
|
||||
&snapshot,
|
||||
sidebar_width,
|
||||
sidebar_collapsed,
|
||||
sidebar_hidden,
|
||||
cx,
|
||||
))
|
||||
.child(self.render_main_pane(&snapshot, &active_tab, sidebar_collapsed, cx)),
|
||||
)
|
||||
.when(hover_expanded, |el| {
|
||||
el.child(self.render_hidden_sidebar_overlay(&snapshot, cx))
|
||||
})
|
||||
.children(render_command_overlay(&snapshot, cx))
|
||||
.into_any_element()
|
||||
}
|
||||
|
||||
fn render_hidden_sidebar_overlay(
|
||||
&mut self,
|
||||
snapshot: &BrowserSnapshot,
|
||||
cx: &mut Context<Self>,
|
||||
) -> AnyElement {
|
||||
div()
|
||||
.absolute()
|
||||
.inset_0()
|
||||
.child(
|
||||
div()
|
||||
.id(SharedString::from("hidden-sidebar-backdrop"))
|
||||
.absolute()
|
||||
.inset_0()
|
||||
.on_click(cx.listener(|shell, _, _, cx| shell.collapse_hidden_sidebar(cx))),
|
||||
)
|
||||
.child(
|
||||
div()
|
||||
.absolute()
|
||||
.top(px(spacing::SHELL_INSET))
|
||||
.left(px(spacing::SHELL_INSET))
|
||||
.bottom(px(spacing::SHELL_INSET))
|
||||
.child(self.render_expanded_sidebar(
|
||||
snapshot,
|
||||
f32::from(DEFAULT_SIDEBAR_WIDTH_PX),
|
||||
cx,
|
||||
)),
|
||||
)
|
||||
.into_any_element()
|
||||
}
|
||||
|
||||
fn render_main_pane(
|
||||
&mut self,
|
||||
snapshot: &BrowserSnapshot,
|
||||
@@ -112,13 +153,31 @@ impl ElyShell {
|
||||
snapshot: &BrowserSnapshot,
|
||||
sidebar_width: f32,
|
||||
sidebar_collapsed: bool,
|
||||
sidebar_hidden: bool,
|
||||
cx: &mut Context<Self>,
|
||||
) -> AnyElement {
|
||||
if sidebar_hidden {
|
||||
return self.render_hidden_sidebar_rail(cx);
|
||||
}
|
||||
if sidebar_collapsed {
|
||||
return self.render_compact_sidebar(snapshot, sidebar_width, cx);
|
||||
}
|
||||
self.render_expanded_sidebar(snapshot, sidebar_width, cx)
|
||||
}
|
||||
|
||||
fn render_hidden_sidebar_rail(&mut self, cx: &mut Context<Self>) -> AnyElement {
|
||||
div()
|
||||
.id(SharedString::from("hidden-sidebar-rail"))
|
||||
.w(px(f32::from(HIDDEN_SIDEBAR_WIDTH_PX)))
|
||||
.h_full()
|
||||
.rounded(px(spacing::RADIUS_PANE))
|
||||
.bg(rgba(0xffffff8c))
|
||||
.cursor_pointer()
|
||||
.hover(|style| style.bg(rgba(0xffffffd9)))
|
||||
.active(|style| style.opacity(0.78))
|
||||
.on_click(cx.listener(|shell, _, _, cx| shell.expand_hidden_sidebar(cx)))
|
||||
.into_any_element()
|
||||
}
|
||||
}
|
||||
|
||||
fn render_error(message: String) -> AnyElement {
|
||||
|
||||
Reference in New Issue
Block a user