Radish alpha
r
Radicle terminal user interface
Radicle
Git (anonymous pull)
Log in to clone via SSH
lib: Add a scrollbar to table widget
Erik Kundt committed 1 year ago
commit a8a6a745941597fe159afb1d1c31f511fe2e438e
parent 5138f419f236a68ac44cbd5db9a6781765cd3e40
1 file changed +38 -10
modified src/ui/widget/list.rs
@@ -1,12 +1,12 @@
use std::cmp;
use std::marker::PhantomData;

-
use ratatui::widgets::{Cell, Row};
+
use ratatui::widgets::{Cell, Row, Scrollbar, ScrollbarState};
use ratatui::Frame;
use termion::event::Key;

-
use ratatui::layout::Constraint;
-
use ratatui::style::Stylize;
+
use ratatui::layout::{Constraint, Layout};
+
use ratatui::style::{Style, Stylize};
use ratatui::text::Text;
use ratatui::widgets::TableState;

@@ -29,7 +29,7 @@ where
    pub items: Vec<R>,
    pub selected: Option<usize>,
    pub columns: Vec<Column<'a>>,
-
    pub has_footer: bool,
+
    pub show_scrollbar: bool,
}

impl<'a, R, const W: usize> Default for TableProps<'a, R, W>
@@ -40,7 +40,7 @@ where
        Self {
            items: vec![],
            columns: vec![],
-
            has_footer: false,
+
            show_scrollbar: true,
            selected: Some(0),
        }
    }
@@ -65,8 +65,8 @@ where
        self
    }

-
    pub fn footer(mut self, has_footer: bool) -> Self {
-
        self.has_footer = has_footer;
+
    pub fn show_scrollbar(mut self, show_scrollbar: bool) -> Self {
+
        self.show_scrollbar = show_scrollbar;
        self
    }
}
@@ -213,6 +213,9 @@ where
            .and_then(|props| props.inner_ref::<TableProps<R, W>>())
            .unwrap_or(&default);

+
        let show_scrollbar = props.show_scrollbar && props.items.len() >= self.height.into();
+
        let has_items = !props.items.is_empty();
+

        let widths: Vec<Constraint> = props
            .columns
            .iter()
@@ -225,7 +228,17 @@ where
            })
            .collect();

-
        if !props.items.is_empty() {
+
        if has_items {
+
            let [table_area, scroller_area] = Layout::horizontal([
+
                Constraint::Min(1),
+
                if show_scrollbar {
+
                    Constraint::Length(1)
+
                } else {
+
                    Constraint::Length(0)
+
                },
+
            ])
+
            .areas(render.area);
+

            let rows = props
                .items
                .iter()
@@ -246,13 +259,28 @@ where
                    Row::new(cells)
                })
                .collect::<Vec<_>>();
+

            let rows = ratatui::widgets::Table::default()
                .rows(rows)
                .widths(widths)
                .column_spacing(1)
                .highlight_style(style::highlight(render.focus));
-

-
            frame.render_stateful_widget(rows, render.area, &mut self.state.0);
+
            frame.render_stateful_widget(rows, table_area, &mut self.state.0);
+

+
            let scroller = Scrollbar::default()
+
                .begin_symbol(None)
+
                .track_symbol(None)
+
                .end_symbol(None)
+
                .thumb_symbol("┃")
+
                .style(if render.focus {
+
                    Style::default()
+
                } else {
+
                    Style::default().dim()
+
                });
+
            let mut scroller_state = ScrollbarState::default()
+
                .content_length(props.items.len().saturating_sub(self.height.into()))
+
                .position(self.state.0.offset());
+
            frame.render_stateful_widget(scroller, scroller_area, &mut scroller_state);
        } else {
            let center = layout::centered_rect(render.area, 50, 10);
            let hint = Text::from(span::default("Nothing to show"))