Skip to main content

sqlly_datatable/grid/
theme.rs

1//! `GridTheme` — typed color set used by the widget. Default is monochrome on
2//! white; downstream code that wants a dark mode or accent palette can
3//! construct a custom theme and pass it on the [`crate::grid::GridState`].
4
5use gpui::Hsla;
6
7#[derive(Clone, Debug)]
8pub struct GridTheme {
9    pub bg: Hsla,
10    pub header_bg: Hsla,
11    pub filter_bg: Hsla,
12    pub filter_active_bg: Hsla,
13    pub row_header_bg: Hsla,
14    pub selection_bg: Hsla,
15    pub alt_row_bg: Hsla,
16    pub grid_line: Hsla,
17    pub header_fg: Hsla,
18    pub text_fg: Hsla,
19    pub negative_fg: Hsla,
20    pub sort_indicator: Hsla,
21    pub filter_cursor: Hsla,
22    /// Background fill of the right-click context menu / filter popup surface.
23    pub menu_bg: Hsla,
24    /// Fill drawn behind the menu item currently under the pointer (hover).
25    pub menu_hover_bg: Hsla,
26    /// Foreground color for menu item labels.
27    pub menu_fg: Hsla,
28}
29
30impl Default for GridTheme {
31    fn default() -> Self {
32        Self {
33            bg: hsla(0.0, 0.0, 1.0, 1.0),
34            header_bg: hsla(0.0, 0.0, 0.93, 1.0),
35            filter_bg: hsla(0.0, 0.0, 0.96, 1.0),
36            filter_active_bg: hsla(0.58, 0.30, 0.85, 1.0),
37            row_header_bg: hsla(0.0, 0.0, 0.90, 1.0),
38            selection_bg: hsla(0.58, 0.50, 0.80, 0.50),
39            alt_row_bg: hsla(0.0, 0.0, 0.95, 1.0),
40            grid_line: hsla(0.0, 0.0, 0.85, 1.0),
41            header_fg: hsla(0.0, 0.0, 0.15, 1.0),
42            text_fg: hsla(0.0, 0.0, 0.1, 1.0),
43            negative_fg: hsla(0.0, 0.75, 0.45, 1.0),
44            sort_indicator: hsla(0.58, 0.50, 0.40, 1.0),
45            filter_cursor: hsla(0.0, 0.0, 0.1, 1.0),
46            menu_bg: hsla(0.0, 0.0, 1.0, 1.0),
47            menu_hover_bg: hsla(0.58, 0.45, 0.85, 1.0),
48            menu_fg: hsla(0.0, 0.0, 0.1, 1.0),
49        }
50    }
51}
52
53fn hsla(h: f32, s: f32, l: f32, a: f32) -> Hsla {
54    Hsla { h, s, l, a }
55}
56
57#[cfg(test)]
58mod tests {
59    use super::*;
60
61    /// The context menu must be paintable from the theme (not a hardcoded
62    /// color), and its hover fill must be visually distinct from the menu
63    /// background so a mouse-over state is actually perceivable. The label
64    /// color must also contrast with the background. This guards the
65    /// dark/light theming + hover-state regression.
66    #[test]
67    fn default_theme_exposes_distinct_menu_colors() {
68        let t = GridTheme::default();
69        // Menu surface must be opaque so it fully covers content beneath it.
70        assert_eq!(t.menu_bg.a, 1.0, "menu background must be opaque");
71        // Hover fill must differ from the surface, else hover is invisible.
72        assert_ne!(
73            t.menu_hover_bg, t.menu_bg,
74            "menu hover fill must differ from the menu background"
75        );
76        // Label color must differ from the surface for legible text.
77        assert_ne!(
78            t.menu_fg, t.menu_bg,
79            "menu label color must contrast with the menu background"
80        );
81    }
82}