facett-demo/src/widget_gallery.rs
//! **`widgets` demo tab** — the facett-app input/data widgets (Fas 4 + extras): a
//! [`TabView`] switches between an [`Accordion`] (hosting a [`Stepper`] and a
//! [`Pagination`]-driven list), a [`Tree`] navigator, and a [`DatePicker`].
use facett_app::{Accordion, ColorPicker, DatePicker, NavItem, NavModel, Pagination, Stepper, TabView, Tree};
use facett_core::{Facet, FacetCaps};
pub struct WidgetGallery {
title: String,
tabs: TabView,
accordion: Accordion,
stepper: Stepper,
pager: Pagination,
rows: Vec<String>,
tree: Tree,
tree_model: NavModel,
cal: DatePicker,
color: ColorPicker,
}
impl WidgetGallery {
pub fn new() -> Self {
let rows: Vec<String> = (1..=95).map(|i| format!("row {i}")).collect();
let mut accordion = Accordion::new();
accordion.set_open("stepper", true);
let tree_model = NavModel::new([
NavItem::new("src", "src").icon("📁").children([
NavItem::new("src.main", "main.rs").icon("📄"),
NavItem::new("src.lib", "lib.rs").icon("📄"),
NavItem::new("src.ui", "ui").icon("📁").children([NavItem::new("src.ui.app", "app.rs").icon("📄")]),
]),
NavItem::new("cargo", "Cargo.toml").icon("📄"),
]);
Self {
title: "widgets".into(),
tabs: TabView::new([("widgets", "Widgets"), ("tree", "Tree"), ("calendar", "Calendar"), ("color", "Color")]),
accordion,
stepper: Stepper::new(3).range(0, 10),
pager: Pagination::new(95, 10),
rows,
tree: Tree::new(),
tree_model,
cal: DatePicker::new(2026, 7).with_selected(2026, 7, 1),
color: ColorPicker::new([90, 200, 140, 255]).swatches([
[224, 90, 90, 255],
[230, 170, 60, 255],
[90, 200, 140, 255],
[70, 130, 220, 255],
]),
}
}
}
impl Default for WidgetGallery {
fn default() -> Self {
Self::new()
}
}
impl Facet for WidgetGallery {
fn title(&self) -> &str {
&self.title
}
fn ui(&mut self, ui: &mut egui::Ui) {
facett::core::navgraph::declare_own_draw_order(ui); // atoms follow the draw order (navgraph §9)
self.tabs.show(ui);
ui.separator();
match self.tabs.active() {
"tree" => {
let Self { tree, tree_model, .. } = self;
tree.show(ui, tree_model);
ui.separator();
ui.weak(format!("selected: {}", tree.selected().unwrap_or("—")));
}
"calendar" => {
self.cal.show(ui);
ui.separator();
let sel = self.cal.selected().map(|(y, m, d)| format!("{y:04}-{m:02}-{d:02}")).unwrap_or_else(|| "—".into());
ui.weak(format!("selected: {sel}"));
}
"color" => {
self.color.show(ui);
ui.separator();
ui.weak(format!("colour: {}", self.color.hex()));
}
_ => {
let Self { accordion, stepper, pager, rows, .. } = self;
accordion.section(ui, "stepper", "Stepper — a bounded integer", |ui| {
stepper.show(ui);
ui.weak(format!("value = {}", stepper.value()));
});
accordion.section(ui, "pager", "Pagination — a paged list", |ui| {
pager.show(ui);
let (start, end) = pager.range();
for r in &rows[start..end] {
ui.label(r);
}
});
}
}
}
fn state_json(&self) -> serde_json::Value {
serde_json::json!({
"tabs": self.tabs.state_json(),
"accordion": self.accordion.state_json(),
"stepper": self.stepper.state_json(),
"pager": self.pager.state_json(),
"tree": self.tree.state_json(),
"calendar": self.cal.state_json(),
"color": self.color.state_json(),
})
}
fn caps(&self) -> FacetCaps {
FacetCaps::NONE.themeable().resizable()
}
}