feat: add native material backgrounds

This commit is contained in:
2026-11-09 09:52:29 +07:00
parent 8c438ed8a6
commit 7784e8d570
14 changed files with 279 additions and 36 deletions
+30 -1
View File
@@ -96,6 +96,7 @@ impl SidebarEntry {
pub struct Sidebar {
id: ElementId,
selected: Option<usize>,
transparent: bool,
a11y_label: Option<SharedString>,
on_change: Option<ChangeHandler>,
entries: Option<EntriesFn>,
@@ -110,6 +111,7 @@ impl Sidebar {
Self {
id: id.into(),
selected: None,
transparent: false,
a11y_label: None,
on_change: None,
entries: None,
@@ -122,6 +124,17 @@ impl Sidebar {
self
}
/// Paints translucent material fills so the window's native backdrop shows through.
pub fn transparent(mut self, transparent: bool) -> Self {
self.transparent = transparent;
self
}
/// Whether translucent material fills are painted.
pub fn is_transparent(&self) -> bool {
self.transparent
}
/// Reports the next selected row, from clicks and keys alike.
pub fn on_change<F>(mut self, handler: F) -> Self
where
@@ -175,6 +188,7 @@ impl RenderOnce for Sidebar {
.clone()
});
let theme = cx.theme();
let material = self.transparent;
let label = self
.a11y_label
@@ -195,6 +209,7 @@ impl RenderOnce for Sidebar {
index,
entries.len(),
self.selected == Some(index),
material,
&self.on_change,
&focus,
)
@@ -207,6 +222,7 @@ impl RenderOnce for Sidebar {
.size_full()
.flex()
.flex_col()
.when(material, |sidebar| sidebar.bg(theme.material.background))
.text_size(theme.sizes.medium.text_size)
.track_focus(&focus)
.focusable()
@@ -237,16 +253,19 @@ impl RenderOnce for Sidebar {
}
}
#[allow(clippy::too_many_arguments)]
fn render_entry(
cx: &App,
entry: &SidebarEntry,
index: usize,
count: usize,
selected: bool,
material: bool,
on_change: &Option<ChangeHandler>,
focus: &FocusHandle,
) -> AnyElement {
let theme = cx.theme();
match entry {
SidebarEntry::Header { label } => div()
.px_2()
@@ -277,7 +296,17 @@ fn render_entry(
.aria_selected(selected)
.aria_position_in_set(index + 1)
.aria_size_of_set(count)
.map(|row| paint_selectable_row(cx, row, selected, *row_disabled));
.map(|row| {
if material && !*row_disabled {
if selected {
row.bg(theme.material.selection)
} else {
row.hover(|row| row.bg(theme.material.hover))
}
} else {
paint_selectable_row(cx, row, selected, *row_disabled)
}
});
if !*row_disabled {
row = row.cursor_pointer().on_click({