Skip to main content

egui_charts/ui_kit/panel_header/
mod.rs

1//! Panel title with right-aligned actions and a separator.
2//!
3//! Use [`PanelHeader`] at the top of a sidebar or host panel.
4
5use crate::localization as l10n;
6use egui::{Align, Layout, Response, RichText, Ui, vec2};
7
8use crate::theme::ThemeExt;
9
10/// Height of the header row, which fits a medium `IconButton`.
11const ROW_HEIGHT: f32 = 28.0;
12
13/// Panel header with title and optional right-aligned actions.
14///
15/// The title is in the theme's title size and strong text colour; actions sit 4 px apart.
16pub struct PanelHeader<'a> {
17    title: &'a str,
18    separator: bool,
19}
20
21impl<'a> PanelHeader<'a> {
22    /// Create a panel header with the given title and a separator below.
23    pub fn new(title: &'a str) -> Self {
24        Self {
25            title,
26            separator: true,
27        }
28    }
29
30    /// Has no effect: every header uses the same title style. Kept for source compatibility.
31    #[must_use]
32    pub fn strong(self) -> Self {
33        self
34    }
35
36    /// Disable the separator below the header.
37    #[must_use]
38    pub fn no_separator(mut self) -> Self {
39        self.separator = false;
40        self
41    }
42
43    /// Show the panel header. The closure receives a right-to-left layout
44    /// for action buttons.
45    pub fn show(self, ui: &mut Ui, actions: impl FnOnce(&mut Ui)) -> Response {
46        let theme = ui.active_theme();
47        let size = vec2(ui.available_width(), ROW_HEIGHT + 2.0 * theme.spacing.sm);
48        let response = ui
49            .allocate_ui_with_layout(size, Layout::right_to_left(Align::Center), |ui| {
50                ui.set_min_height(size.y);
51                ui.spacing_mut().item_spacing.x = theme.spacing.sm;
52                actions(ui);
53                ui.with_layout(Layout::left_to_right(Align::Center), |ui| {
54                    ui.add(
55                        egui::Label::new(
56                            RichText::new(l10n::text(ui.ctx(), self.title))
57                                .strong()
58                                .size(theme.text.title),
59                        )
60                        .truncate(),
61                    );
62                });
63            })
64            .response;
65
66        if self.separator {
67            ui.separator();
68        }
69
70        response
71    }
72
73    /// Show the panel header with no action buttons.
74    pub fn show_plain(self, ui: &mut Ui) -> Response {
75        self.show(ui, |_| {})
76    }
77}