Skip to content

Commit

Permalink
Update README
Browse files Browse the repository at this point in the history
  • Loading branch information
Philipp Reiter committed Aug 10, 2024
1 parent 55a1f77 commit 7dfd0f8
Show file tree
Hide file tree
Showing 4 changed files with 83 additions and 85 deletions.
90 changes: 44 additions & 46 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,24 +6,22 @@

</div>

This crate provides a stateful widget [`List`] implementation for `Ratatui`, enabling listing
widgets that implement the [`PreRender`] trait. The associated [`ListState`], offers functionalities
such as navigating to the next and previous items.
Additionally, the lists support both horizontal and vertical scrolling.
This crate provides a stateful widget [`ListView`] implementation for `Ratatui`. The associated [`ListState`], offers functionalities such as navigating to the next and previous items.
The list view support both horizontal and vertical scrolling.

### Configuration
The [`List`] can be customized with the following options:
- [`List::scroll_direction`]: Specifies whether the list is vertically or horizontally scrollable.
- [`List::style`]: Defines the base style of the list.
- [`List::block`]: Optional outer block surrounding the list.
The [`ListView`] can be customized with the following options:
- [`ListView::scroll_axis`]: Specifies whether the list is vertically or horizontally scrollable.
- [`ListView::style`]: Defines the base style of the list.
- [`ListView::block`]: Optional outer block surrounding the list.

You can adjust the behavior of [`ListState`] with the following options:
- [`ListState::circular`]: Determines if the selection is circular. When enabled, selecting the last item loops back to the first. Enabled by default.

### Example
```rust
use ratatui::prelude::*;
use tui_widget_list::{List, ListState, PreRender, PreRenderContext};
use tui_widget_list::{ListBuilder, ListState, ListView};

#[derive(Debug, Clone)]
pub struct ListItem {
Expand All @@ -40,51 +38,49 @@ impl ListItem {
}
}

impl PreRender for ListItem {
fn pre_render(&mut self, context: &PreRenderContext) -> u16 {
// Set alternating styles
if context.index % 2 == 0 {
self.style = Style::default().bg(Color::Rgb(28, 28, 32));
} else {
self.style = Style::default().bg(Color::Rgb(0, 0, 0));
}

// Highlight the selected widget
if context.is_selected {
self.style = Style::default()
.bg(Color::Rgb(255, 153, 0))
.fg(Color::Rgb(28, 28, 32));
};

// Example: set main axis size to 1
let main_axis_size = 1;

main_axis_size
}
}

impl Widget for ListItem {
fn render(self, area: Rect, buf: &mut Buffer) {
Line::from(self.text).style(self.style).render(area, buf);
}
}

pub fn render(f: &mut Frame) {
let list = List::new(vec![
ListItem::new("Item 1"),
ListItem::new("Item 2"),
]);
let mut state = ListState::default();
f.render_stateful_widget(list, f.size(), &mut state);
pub struct App {
state: ListState,
}
```

### Long lists

`tui-widget-list` also allows to render long lists with thousands of items efficiently.
Check out the [example](https://github.com/preiter93/tui-widget-list/tree/main/examples/long.rs)
for demonstration. Note that the key is to create the items only once and implement `Widget` and
`PreRender` on the references to the list item.
impl Widget for &mut App {
fn render(self, area: Rect, buf: &mut Buffer) {
let builder = ListBuilder::new(|context| {
let mut item = ListItem::new(&format!("Item {:0}", context.index));

// Alternating styles
if context.index % 2 == 0 {
item.style = Style::default().bg(Color::Rgb(28, 28, 32));
} else {
item.style = Style::default().bg(Color::Rgb(0, 0, 0));
}

// Style the selected element
if context.is_selected {
item.style = Style::default()
.bg(Color::Rgb(255, 153, 0))
.fg(Color::Rgb(28, 28, 32));
};

// Return the size of the widget along the main axis.
let main_axis_size = 1;

(item, main_axis_size)
});

let item_count = 2;
let list = ListView::new(builder, item_count);
let state = &mut self.state;

list.render(area, buf, state);
}
}
```

For more examples see [tui-widget-list](https://github.com/preiter93/tui-widget-list/tree/main/examples).

Expand All @@ -100,3 +96,5 @@ For more examples see [tui-widget-list](https://github.com/preiter93/tui-widget-
#### Vertically and horizontally scrollable

![](examples/tapes/demo.gif?v=1)

License: MIT
5 changes: 1 addition & 4 deletions examples/demo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,10 +78,7 @@ impl ColoredContainer {
}

impl Widget for ColoredContainer {
fn render(self, area: Rect, buf: &mut Buffer)
where
Self: Sized,
{
fn render(self, area: Rect, buf: &mut Buffer) {
Block::default()
.borders(Borders::ALL)
.border_style(self.border_style)
Expand Down
5 changes: 1 addition & 4 deletions examples/simple.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,10 +59,7 @@ impl App {
}

impl Widget for &mut App {
fn render(self, area: Rect, buf: &mut Buffer)
where
Self: Sized,
{
fn render(self, area: Rect, buf: &mut Buffer) {
let builder = ListBuilder::new(|context| {
let text = format!("Item {0}", context.index);
let mut item = Line::from(text);
Expand Down
68 changes: 37 additions & 31 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@
//! - [`ListState::circular`]: Determines if the selection is circular. When enabled, selecting the last item loops back to the first. Enabled by default.
//!
//! ## Example
//! ```
//!```
//! use ratatui::prelude::*;
//! use tui_widget_list::{ListView, ListState, ListBuilder};
//! use tui_widget_list::{ListBuilder, ListState, ListView};
//!
//! #[derive(Debug, Clone)]
//! pub struct ListItem {
Expand All @@ -44,37 +44,43 @@
//! }
//! }
//!
//! pub fn render(f: &mut Frame) {
//! let builder = ListBuilder::new(|context| {
//! let mut item = ListItem::new(&format!("Item {:0}", context.index));
//!
//! // Alternating styles
//! if context.index % 2 == 0 {
//! item.style = Style::default().bg(Color::Rgb(28, 28, 32));
//! } else {
//! item.style = Style::default().bg(Color::Rgb(0, 0, 0));
//! }
//!
//! // Style the selected element
//! if context.is_selected {
//! item.style = Style::default()
//! .bg(Color::Rgb(255, 153, 0))
//! .fg(Color::Rgb(28, 28, 32));
//! };
//!
//! // Return the size of the widget along the main axis.
//! let main_axis_size = 1;
//!
//! (item, main_axis_size)
//! });
//!
//! let mut state = ListState::default();
//! let item_count = 2;
//! let list = ListView::new(builder, item_count);
//! pub struct App {
//! state: ListState,
//! }
//!
//! f.render_stateful_widget(list, f.size(), &mut state);
//! impl Widget for &mut App {
//! fn render(self, area: Rect, buf: &mut Buffer) {
//! let builder = ListBuilder::new(|context| {
//! let mut item = ListItem::new(&format!("Item {:0}", context.index));
//!
//! // Alternating styles
//! if context.index % 2 == 0 {
//! item.style = Style::default().bg(Color::Rgb(28, 28, 32));
//! } else {
//! item.style = Style::default().bg(Color::Rgb(0, 0, 0));
//! }
//!
//! // Style the selected element
//! if context.is_selected {
//! item.style = Style::default()
//! .bg(Color::Rgb(255, 153, 0))
//! .fg(Color::Rgb(28, 28, 32));
//! };
//!
//! // Return the size of the widget along the main axis.
//! let main_axis_size = 1;
//!
//! (item, main_axis_size)
//! });
//!
//! let item_count = 2;
//! let list = ListView::new(builder, item_count);
//! let state = &mut self.state;
//!
//! list.render(area, buf, state);
//! }
//! }
//! ```
//!```
//!
//! For more examples see [tui-widget-list](https://github.com/preiter93/tui-widget-list/tree/main/examples).
//!
Expand Down

0 comments on commit 7dfd0f8

Please sign in to comment.