use crate::styles::typography;
use crate::tokens::DESIGN_TOKENS;
use egui::{Pos2, Rect, Sense, Ui, Vec2};
use egui_extras::{Size, StripBuilder};
pub struct SidebarLayout {
sidebar_width: f32,
}
impl SidebarLayout {
pub fn new(sidebar_width: f32) -> Self {
Self { sidebar_width }
}
pub fn show(self, ui: &mut Ui, sidebar: impl FnOnce(&mut Ui), content: impl FnOnce(&mut Ui)) {
StripBuilder::new(ui)
.size(Size::exact(self.sidebar_width))
.size(Size::exact(1.0)) .size(Size::remainder())
.horizontal(|mut strip| {
strip.cell(|ui| {
sidebar(ui);
});
strip.cell(|ui| {
let rect = ui.available_rect_before_wrap();
ui.painter().rect_filled(
rect,
0.0,
ui.style().visuals.widgets.noninteractive.bg_stroke.color,
);
});
strip.cell(|ui| {
content(ui);
});
});
}
}
pub struct SidebarTab<'a> {
label: &'a str,
icon: Option<&'a crate::icons::Icon>,
is_active: bool,
}
impl<'a> SidebarTab<'a> {
pub fn new(label: &'a str, is_active: bool) -> Self {
Self {
label,
icon: None,
is_active,
}
}
pub fn icon(mut self, icon: &'a crate::icons::Icon) -> Self {
self.icon = Some(icon);
self
}
pub fn show(self, ui: &mut Ui) -> bool {
let width = ui.available_width();
let height = DESIGN_TOKENS.sizing.button_lg;
let (rect, response) = ui.allocate_exact_size(Vec2::new(width, height), Sense::click());
let is_hovered = response.hovered();
if self.is_active {
ui.painter().rect_filled(
rect,
0.0,
ui.style().visuals.selection.bg_fill.gamma_multiply(0.3),
);
} else if is_hovered {
ui.painter()
.rect_filled(rect, 0.0, ui.style().visuals.widgets.hovered.bg_fill);
}
let text_color = if self.is_active {
ui.style().visuals.selection.bg_fill
} else {
ui.style().visuals.text_color()
};
let mut text_x = rect.min.x + DESIGN_TOKENS.spacing.xl;
if let Some(icon) = self.icon {
let icon_size = DESIGN_TOKENS.sizing.icon_md;
let icon_rect = Rect::from_min_size(
Pos2::new(text_x, rect.center().y - icon_size / 2.0),
Vec2::splat(icon_size),
);
icon.as_image_tinted(icon_rect.size(), text_color)
.paint_at(ui, icon_rect);
text_x = icon_rect.max.x + DESIGN_TOKENS.spacing.sm;
}
ui.painter().text(
Pos2::new(text_x, rect.center().y),
egui::Align2::LEFT_CENTER,
self.label,
egui::FontId::proportional(typography::MD),
text_color,
);
response.clicked()
}
}