use egui::{FontId, Stroke, TextStyle, Ui, Widget, vec2};
use super::corner;
use crate::{Elevation, Icon, RADIUS, SPACING, palette_of};
pub struct Card<'a> {
title: Option<&'a str>,
subtitle: Option<&'a str>,
elevation: Elevation,
}
impl<'a> Default for Card<'a> {
fn default() -> Self {
Self::new()
}
}
impl<'a> Card<'a> {
pub fn new() -> Self {
Self {
title: None,
subtitle: None,
elevation: Elevation::Card,
}
}
pub fn title(mut self, title: &'a str) -> Self {
self.title = Some(title);
self
}
pub fn subtitle(mut self, sub: &'a str) -> Self {
self.subtitle = Some(sub);
self
}
pub fn elevation(mut self, elevation: Elevation) -> Self {
self.elevation = elevation;
self
}
pub fn show<R>(self, ui: &mut Ui, body: impl FnOnce(&mut Ui) -> R) -> R {
let palette = palette_of(ui.ctx());
let frame = egui::Frame::default()
.fill(palette.bg_surface)
.stroke(Stroke::new(1.0, palette.border_subtle))
.corner_radius(corner(RADIUS.md))
.inner_margin(egui::Margin::same(SPACING.s4 as i8))
.shadow(self.elevation.shadow(palette.dark_mode));
frame
.show(ui, |ui| {
if let Some(title) = self.title {
ui.label(
egui::RichText::new(title)
.text_style(TextStyle::Name("h3".into()))
.color(palette.text_primary),
);
}
if let Some(sub) = self.subtitle {
ui.label(
egui::RichText::new(sub)
.text_style(TextStyle::Small)
.color(palette.text_secondary),
);
}
if self.title.is_some() || self.subtitle.is_some() {
ui.add_space(SPACING.s3);
}
body(ui)
})
.inner
}
}
pub struct EmptyState<'a> {
icon: Icon,
title: &'a str,
body: Option<&'a str>,
}
impl<'a> EmptyState<'a> {
pub fn new(icon: Icon, title: &'a str) -> Self {
Self {
icon,
title,
body: None,
}
}
pub fn body(mut self, body: &'a str) -> Self {
self.body = Some(body);
self
}
}
impl<'a> Widget for EmptyState<'a> {
fn ui(self, ui: &mut Ui) -> egui::Response {
let palette = palette_of(ui.ctx());
ui.vertical_centered(|ui| {
ui.add_space(SPACING.s5);
let rect = ui
.allocate_exact_size(vec2(48.0, 48.0), egui::Sense::hover())
.0;
self.icon.paint(ui.painter(), rect, palette.text_tertiary);
ui.add_space(SPACING.s3);
ui.label(
egui::RichText::new(self.title)
.font(FontId::new(16.0, egui::FontFamily::Proportional))
.color(palette.text_primary),
);
if let Some(body) = self.body {
ui.add_space(SPACING.s1);
ui.label(
egui::RichText::new(body)
.text_style(TextStyle::Body)
.color(palette.text_secondary),
);
}
ui.add_space(SPACING.s5);
})
.response
}
}