Struct Scrollbar

Source
pub struct Scrollbar<'a> { /* private fields */ }
Expand description

A widget to display a scrollbar

The following components of the scrollbar are customizable in symbol and style. Note the scrollbar is represented horizontally but it can also be set vertically (which is actually the default).

<--▮------->
^  ^   ^   ^
│  │   │   └ end
│  │   └──── track
│  └──────── thumb
└─────────── begin

§Important

You must specify the ScrollbarState::content_length before rendering the Scrollbar, or else the Scrollbar will render blank.

§Examples

use ratatui::{
    layout::{Margin, Rect},
    text::Line,
    widgets::{
        Block, Borders, Paragraph, Scrollbar, ScrollbarOrientation, ScrollbarState,
        StatefulWidget,
    },
    Frame,
};

let vertical_scroll = 0; // from app state

let items = vec![
    Line::from("Item 1"),
    Line::from("Item 2"),
    Line::from("Item 3"),
];
let paragraph = Paragraph::new(items.clone())
    .scroll((vertical_scroll as u16, 0))
    .block(Block::new().borders(Borders::RIGHT)); // to show a background for the scrollbar

let scrollbar = Scrollbar::new(ScrollbarOrientation::VerticalRight)
    .begin_symbol(Some("↑"))
    .end_symbol(Some("↓"));

let mut scrollbar_state = ScrollbarState::new(items.len()).position(vertical_scroll);

let area = frame.area();
// Note we render the paragraph
frame.render_widget(paragraph, area);
// and the scrollbar, those are separate widgets
frame.render_stateful_widget(
    scrollbar,
    area.inner(Margin {
        // using an inner vertical margin of 1 unit makes the scrollbar inside the block
        vertical: 1,
        horizontal: 0,
    }),
    &mut scrollbar_state,
);

Implementations§

Source§

impl<'a> Scrollbar<'a>

Source

pub const fn new(orientation: ScrollbarOrientation) -> Self

Creates a new scrollbar with the given orientation.

Most of the time you’ll want ScrollbarOrientation::VerticalRight or ScrollbarOrientation::HorizontalBottom. See ScrollbarOrientation for more options.

Examples found in repository?
examples/demo2/tabs/recipe.rs (line 179)
174fn render_scrollbar(position: usize, area: Rect, buf: &mut Buffer) {
175    let mut state = ScrollbarState::default()
176        .content_length(INGREDIENTS.len())
177        .viewport_content_length(6)
178        .position(position);
179    Scrollbar::new(ScrollbarOrientation::VerticalRight)
180        .begin_symbol(None)
181        .end_symbol(None)
182        .track_symbol(None)
183        .thumb_symbol("▐")
184        .render(area, buf, &mut state);
185}
More examples
Hide additional examples
examples/flex.rs (line 344)
307    fn render_demo(self, area: Rect, buf: &mut Buffer) -> bool {
308        // render demo content into a separate buffer so all examples fit we add an extra
309        // area.height to make sure the last example is fully visible even when the scroll offset is
310        // at the max
311        let height = example_height();
312        let demo_area = Rect::new(0, 0, area.width, height);
313        let mut demo_buf = Buffer::empty(demo_area);
314
315        let scrollbar_needed = self.scroll_offset != 0 || height > area.height;
316        let content_area = if scrollbar_needed {
317            Rect {
318                width: demo_area.width - 1,
319                ..demo_area
320            }
321        } else {
322            demo_area
323        };
324
325        let mut spacing = self.spacing;
326        self.selected_tab
327            .render(content_area, &mut demo_buf, &mut spacing);
328
329        let visible_content = demo_buf
330            .content
331            .into_iter()
332            .skip((area.width * self.scroll_offset) as usize)
333            .take(area.area() as usize);
334        for (i, cell) in visible_content.enumerate() {
335            let x = i as u16 % area.width;
336            let y = i as u16 / area.width;
337            buf[(area.x + x, area.y + y)] = cell;
338        }
339
340        if scrollbar_needed {
341            let area = area.intersection(buf.area);
342            let mut state = ScrollbarState::new(max_scroll_offset() as usize)
343                .position(self.scroll_offset as usize);
344            Scrollbar::new(ScrollbarOrientation::VerticalRight).render(area, buf, &mut state);
345        }
346        scrollbar_needed
347    }
examples/scrollbar.rs (line 148)
92    fn draw(&mut self, frame: &mut Frame) {
93        let area = frame.area();
94
95        // Words made "loooong" to demonstrate line breaking.
96        let s =
97            "Veeeeeeeeeeeeeeeery    loooooooooooooooooong   striiiiiiiiiiiiiiiiiiiiiiiiiing.   ";
98        let mut long_line = s.repeat(usize::from(area.width) / s.len() + 4);
99        long_line.push('\n');
100
101        let chunks = Layout::vertical([
102            Constraint::Min(1),
103            Constraint::Percentage(25),
104            Constraint::Percentage(25),
105            Constraint::Percentage(25),
106            Constraint::Percentage(25),
107        ])
108        .split(area);
109
110        let text = vec![
111            Line::from("This is a line "),
112            Line::from("This is a line   ".red()),
113            Line::from("This is a line".on_dark_gray()),
114            Line::from("This is a longer line".crossed_out()),
115            Line::from(long_line.clone()),
116            Line::from("This is a line".reset()),
117            Line::from(vec![
118                Span::raw("Masked text: "),
119                Span::styled(Masked::new("password", '*'), Style::new().fg(Color::Red)),
120            ]),
121            Line::from("This is a line "),
122            Line::from("This is a line   ".red()),
123            Line::from("This is a line".on_dark_gray()),
124            Line::from("This is a longer line".crossed_out()),
125            Line::from(long_line.clone()),
126            Line::from("This is a line".reset()),
127            Line::from(vec![
128                Span::raw("Masked text: "),
129                Span::styled(Masked::new("password", '*'), Style::new().fg(Color::Red)),
130            ]),
131        ];
132        self.vertical_scroll_state = self.vertical_scroll_state.content_length(text.len());
133        self.horizontal_scroll_state = self.horizontal_scroll_state.content_length(long_line.len());
134
135        let create_block = |title: &'static str| Block::bordered().gray().title(title.bold());
136
137        let title = Block::new()
138            .title_alignment(Alignment::Center)
139            .title("Use h j k l or ◄ ▲ ▼ ► to scroll ".bold());
140        frame.render_widget(title, chunks[0]);
141
142        let paragraph = Paragraph::new(text.clone())
143            .gray()
144            .block(create_block("Vertical scrollbar with arrows"))
145            .scroll((self.vertical_scroll as u16, 0));
146        frame.render_widget(paragraph, chunks[1]);
147        frame.render_stateful_widget(
148            Scrollbar::new(ScrollbarOrientation::VerticalRight)
149                .begin_symbol(Some("↑"))
150                .end_symbol(Some("↓")),
151            chunks[1],
152            &mut self.vertical_scroll_state,
153        );
154
155        let paragraph = Paragraph::new(text.clone())
156            .gray()
157            .block(create_block(
158                "Vertical scrollbar without arrows, without track symbol and mirrored",
159            ))
160            .scroll((self.vertical_scroll as u16, 0));
161        frame.render_widget(paragraph, chunks[2]);
162        frame.render_stateful_widget(
163            Scrollbar::new(ScrollbarOrientation::VerticalLeft)
164                .symbols(scrollbar::VERTICAL)
165                .begin_symbol(None)
166                .track_symbol(None)
167                .end_symbol(None),
168            chunks[2].inner(Margin {
169                vertical: 1,
170                horizontal: 0,
171            }),
172            &mut self.vertical_scroll_state,
173        );
174
175        let paragraph = Paragraph::new(text.clone())
176            .gray()
177            .block(create_block(
178                "Horizontal scrollbar with only begin arrow & custom thumb symbol",
179            ))
180            .scroll((0, self.horizontal_scroll as u16));
181        frame.render_widget(paragraph, chunks[3]);
182        frame.render_stateful_widget(
183            Scrollbar::new(ScrollbarOrientation::HorizontalBottom)
184                .thumb_symbol("🬋")
185                .end_symbol(None),
186            chunks[3].inner(Margin {
187                vertical: 0,
188                horizontal: 1,
189            }),
190            &mut self.horizontal_scroll_state,
191        );
192
193        let paragraph = Paragraph::new(text.clone())
194            .gray()
195            .block(create_block(
196                "Horizontal scrollbar without arrows & custom thumb and track symbol",
197            ))
198            .scroll((0, self.horizontal_scroll as u16));
199        frame.render_widget(paragraph, chunks[4]);
200        frame.render_stateful_widget(
201            Scrollbar::new(ScrollbarOrientation::HorizontalBottom)
202                .thumb_symbol("░")
203                .track_symbol(Some("─")),
204            chunks[4].inner(Margin {
205                vertical: 0,
206                horizontal: 1,
207            }),
208            &mut self.horizontal_scroll_state,
209        );
210    }
Source

pub const fn orientation(self, orientation: ScrollbarOrientation) -> Self

Sets the position of the scrollbar.

The orientation of the scrollbar is the position it will take around a Rect. See ScrollbarOrientation for more details.

Resets the symbols to DOUBLE_VERTICAL or DOUBLE_HORIZONTAL based on orientation.

This is a fluent setter method which must be chained or used as it consumes self

Examples found in repository?
examples/table.rs (line 272)
269    fn render_scrollbar(&mut self, frame: &mut Frame, area: Rect) {
270        frame.render_stateful_widget(
271            Scrollbar::default()
272                .orientation(ScrollbarOrientation::VerticalRight)
273                .begin_symbol(None)
274                .end_symbol(None),
275            area.inner(Margin {
276                vertical: 1,
277                horizontal: 1,
278            }),
279            &mut self.scroll_state,
280        );
281    }
More examples
Hide additional examples
examples/demo2/tabs/traceroute.rs (line 79)
53fn render_hops(selected_row: usize, area: Rect, buf: &mut Buffer) {
54    let mut state = TableState::default().with_selected(Some(selected_row));
55    let rows = HOPS.iter().map(|hop| Row::new(vec![hop.host, hop.address]));
56    let block = Block::new()
57        .padding(Padding::new(1, 1, 1, 1))
58        .title_alignment(Alignment::Center)
59        .title("Traceroute bad.horse".bold().white());
60    StatefulWidget::render(
61        Table::new(rows, [Constraint::Max(100), Constraint::Length(15)])
62            .header(Row::new(vec!["Host", "Address"]).set_style(THEME.traceroute.header))
63            .row_highlight_style(THEME.traceroute.selected)
64            .block(block),
65        area,
66        buf,
67        &mut state,
68    );
69    let mut scrollbar_state = ScrollbarState::default()
70        .content_length(HOPS.len())
71        .position(selected_row);
72    let area = Rect {
73        width: area.width + 1,
74        y: area.y + 3,
75        height: area.height - 4,
76        ..area
77    };
78    Scrollbar::default()
79        .orientation(ScrollbarOrientation::VerticalLeft)
80        .begin_symbol(None)
81        .end_symbol(None)
82        .track_symbol(None)
83        .thumb_symbol("▌")
84        .render(area, buf, &mut scrollbar_state);
85}
Source

pub const fn orientation_and_symbol( self, orientation: ScrollbarOrientation, symbols: Set, ) -> Self

Sets the orientation and symbols for the scrollbar from a Set.

This has the same effect as calling Scrollbar::orientation and then Scrollbar::symbols. See those for more details.

This is a fluent setter method which must be chained or used as it consumes self

Source

pub const fn thumb_symbol(self, thumb_symbol: &'a str) -> Self

Sets the symbol that represents the thumb of the scrollbar.

The thumb is the handle representing the progression on the scrollbar. See Scrollbar for a visual example of what this represents.

This is a fluent setter method which must be chained or used as it consumes self

Examples found in repository?
examples/demo2/tabs/recipe.rs (line 183)
174fn render_scrollbar(position: usize, area: Rect, buf: &mut Buffer) {
175    let mut state = ScrollbarState::default()
176        .content_length(INGREDIENTS.len())
177        .viewport_content_length(6)
178        .position(position);
179    Scrollbar::new(ScrollbarOrientation::VerticalRight)
180        .begin_symbol(None)
181        .end_symbol(None)
182        .track_symbol(None)
183        .thumb_symbol("▐")
184        .render(area, buf, &mut state);
185}
More examples
Hide additional examples
examples/demo2/tabs/traceroute.rs (line 83)
53fn render_hops(selected_row: usize, area: Rect, buf: &mut Buffer) {
54    let mut state = TableState::default().with_selected(Some(selected_row));
55    let rows = HOPS.iter().map(|hop| Row::new(vec![hop.host, hop.address]));
56    let block = Block::new()
57        .padding(Padding::new(1, 1, 1, 1))
58        .title_alignment(Alignment::Center)
59        .title("Traceroute bad.horse".bold().white());
60    StatefulWidget::render(
61        Table::new(rows, [Constraint::Max(100), Constraint::Length(15)])
62            .header(Row::new(vec!["Host", "Address"]).set_style(THEME.traceroute.header))
63            .row_highlight_style(THEME.traceroute.selected)
64            .block(block),
65        area,
66        buf,
67        &mut state,
68    );
69    let mut scrollbar_state = ScrollbarState::default()
70        .content_length(HOPS.len())
71        .position(selected_row);
72    let area = Rect {
73        width: area.width + 1,
74        y: area.y + 3,
75        height: area.height - 4,
76        ..area
77    };
78    Scrollbar::default()
79        .orientation(ScrollbarOrientation::VerticalLeft)
80        .begin_symbol(None)
81        .end_symbol(None)
82        .track_symbol(None)
83        .thumb_symbol("▌")
84        .render(area, buf, &mut scrollbar_state);
85}
examples/demo2/tabs/email.rs (line 120)
82fn render_inbox(selected_index: usize, area: Rect, buf: &mut Buffer) {
83    let vertical = Layout::vertical([Constraint::Length(1), Constraint::Min(0)]);
84    let [tabs, inbox] = vertical.areas(area);
85    let theme = THEME.email;
86    Tabs::new(vec![" Inbox ", " Sent ", " Drafts "])
87        .style(theme.tabs)
88        .highlight_style(theme.tabs_selected)
89        .select(0)
90        .divider("")
91        .render(tabs, buf);
92
93    let highlight_symbol = ">>";
94    let from_width = EMAILS
95        .iter()
96        .map(|e| e.from.width())
97        .max()
98        .unwrap_or_default();
99    let items = EMAILS.iter().map(|e| {
100        let from = format!("{:width$}", e.from, width = from_width).into();
101        ListItem::new(Line::from(vec![from, " ".into(), e.subject.into()]))
102    });
103    let mut state = ListState::default().with_selected(Some(selected_index));
104    StatefulWidget::render(
105        List::new(items)
106            .style(theme.inbox)
107            .highlight_style(theme.selected_item)
108            .highlight_symbol(highlight_symbol),
109        inbox,
110        buf,
111        &mut state,
112    );
113    let mut scrollbar_state = ScrollbarState::default()
114        .content_length(EMAILS.len())
115        .position(selected_index);
116    Scrollbar::default()
117        .begin_symbol(None)
118        .end_symbol(None)
119        .track_symbol(None)
120        .thumb_symbol("▐")
121        .render(inbox, buf, &mut scrollbar_state);
122}
examples/scrollbar.rs (line 184)
92    fn draw(&mut self, frame: &mut Frame) {
93        let area = frame.area();
94
95        // Words made "loooong" to demonstrate line breaking.
96        let s =
97            "Veeeeeeeeeeeeeeeery    loooooooooooooooooong   striiiiiiiiiiiiiiiiiiiiiiiiiing.   ";
98        let mut long_line = s.repeat(usize::from(area.width) / s.len() + 4);
99        long_line.push('\n');
100
101        let chunks = Layout::vertical([
102            Constraint::Min(1),
103            Constraint::Percentage(25),
104            Constraint::Percentage(25),
105            Constraint::Percentage(25),
106            Constraint::Percentage(25),
107        ])
108        .split(area);
109
110        let text = vec![
111            Line::from("This is a line "),
112            Line::from("This is a line   ".red()),
113            Line::from("This is a line".on_dark_gray()),
114            Line::from("This is a longer line".crossed_out()),
115            Line::from(long_line.clone()),
116            Line::from("This is a line".reset()),
117            Line::from(vec![
118                Span::raw("Masked text: "),
119                Span::styled(Masked::new("password", '*'), Style::new().fg(Color::Red)),
120            ]),
121            Line::from("This is a line "),
122            Line::from("This is a line   ".red()),
123            Line::from("This is a line".on_dark_gray()),
124            Line::from("This is a longer line".crossed_out()),
125            Line::from(long_line.clone()),
126            Line::from("This is a line".reset()),
127            Line::from(vec![
128                Span::raw("Masked text: "),
129                Span::styled(Masked::new("password", '*'), Style::new().fg(Color::Red)),
130            ]),
131        ];
132        self.vertical_scroll_state = self.vertical_scroll_state.content_length(text.len());
133        self.horizontal_scroll_state = self.horizontal_scroll_state.content_length(long_line.len());
134
135        let create_block = |title: &'static str| Block::bordered().gray().title(title.bold());
136
137        let title = Block::new()
138            .title_alignment(Alignment::Center)
139            .title("Use h j k l or ◄ ▲ ▼ ► to scroll ".bold());
140        frame.render_widget(title, chunks[0]);
141
142        let paragraph = Paragraph::new(text.clone())
143            .gray()
144            .block(create_block("Vertical scrollbar with arrows"))
145            .scroll((self.vertical_scroll as u16, 0));
146        frame.render_widget(paragraph, chunks[1]);
147        frame.render_stateful_widget(
148            Scrollbar::new(ScrollbarOrientation::VerticalRight)
149                .begin_symbol(Some("↑"))
150                .end_symbol(Some("↓")),
151            chunks[1],
152            &mut self.vertical_scroll_state,
153        );
154
155        let paragraph = Paragraph::new(text.clone())
156            .gray()
157            .block(create_block(
158                "Vertical scrollbar without arrows, without track symbol and mirrored",
159            ))
160            .scroll((self.vertical_scroll as u16, 0));
161        frame.render_widget(paragraph, chunks[2]);
162        frame.render_stateful_widget(
163            Scrollbar::new(ScrollbarOrientation::VerticalLeft)
164                .symbols(scrollbar::VERTICAL)
165                .begin_symbol(None)
166                .track_symbol(None)
167                .end_symbol(None),
168            chunks[2].inner(Margin {
169                vertical: 1,
170                horizontal: 0,
171            }),
172            &mut self.vertical_scroll_state,
173        );
174
175        let paragraph = Paragraph::new(text.clone())
176            .gray()
177            .block(create_block(
178                "Horizontal scrollbar with only begin arrow & custom thumb symbol",
179            ))
180            .scroll((0, self.horizontal_scroll as u16));
181        frame.render_widget(paragraph, chunks[3]);
182        frame.render_stateful_widget(
183            Scrollbar::new(ScrollbarOrientation::HorizontalBottom)
184                .thumb_symbol("🬋")
185                .end_symbol(None),
186            chunks[3].inner(Margin {
187                vertical: 0,
188                horizontal: 1,
189            }),
190            &mut self.horizontal_scroll_state,
191        );
192
193        let paragraph = Paragraph::new(text.clone())
194            .gray()
195            .block(create_block(
196                "Horizontal scrollbar without arrows & custom thumb and track symbol",
197            ))
198            .scroll((0, self.horizontal_scroll as u16));
199        frame.render_widget(paragraph, chunks[4]);
200        frame.render_stateful_widget(
201            Scrollbar::new(ScrollbarOrientation::HorizontalBottom)
202                .thumb_symbol("░")
203                .track_symbol(Some("─")),
204            chunks[4].inner(Margin {
205                vertical: 0,
206                horizontal: 1,
207            }),
208            &mut self.horizontal_scroll_state,
209        );
210    }
Source

pub fn thumb_style<S: Into<Style>>(self, thumb_style: S) -> Self

Sets the style on the scrollbar thumb.

The thumb is the handle representing the progression on the scrollbar. See Scrollbar for a visual example of what this represents.

style accepts any type that is convertible to Style (e.g. Style, Color, or your own type that implements Into<Style>).

This is a fluent setter method which must be chained or used as it consumes self

Source

pub const fn track_symbol(self, track_symbol: Option<&'a str>) -> Self

Sets the symbol that represents the track of the scrollbar.

See Scrollbar for a visual example of what this represents.

This is a fluent setter method which must be chained or used as it consumes self

Examples found in repository?
examples/demo2/tabs/recipe.rs (line 182)
174fn render_scrollbar(position: usize, area: Rect, buf: &mut Buffer) {
175    let mut state = ScrollbarState::default()
176        .content_length(INGREDIENTS.len())
177        .viewport_content_length(6)
178        .position(position);
179    Scrollbar::new(ScrollbarOrientation::VerticalRight)
180        .begin_symbol(None)
181        .end_symbol(None)
182        .track_symbol(None)
183        .thumb_symbol("▐")
184        .render(area, buf, &mut state);
185}
More examples
Hide additional examples
examples/demo2/tabs/traceroute.rs (line 82)
53fn render_hops(selected_row: usize, area: Rect, buf: &mut Buffer) {
54    let mut state = TableState::default().with_selected(Some(selected_row));
55    let rows = HOPS.iter().map(|hop| Row::new(vec![hop.host, hop.address]));
56    let block = Block::new()
57        .padding(Padding::new(1, 1, 1, 1))
58        .title_alignment(Alignment::Center)
59        .title("Traceroute bad.horse".bold().white());
60    StatefulWidget::render(
61        Table::new(rows, [Constraint::Max(100), Constraint::Length(15)])
62            .header(Row::new(vec!["Host", "Address"]).set_style(THEME.traceroute.header))
63            .row_highlight_style(THEME.traceroute.selected)
64            .block(block),
65        area,
66        buf,
67        &mut state,
68    );
69    let mut scrollbar_state = ScrollbarState::default()
70        .content_length(HOPS.len())
71        .position(selected_row);
72    let area = Rect {
73        width: area.width + 1,
74        y: area.y + 3,
75        height: area.height - 4,
76        ..area
77    };
78    Scrollbar::default()
79        .orientation(ScrollbarOrientation::VerticalLeft)
80        .begin_symbol(None)
81        .end_symbol(None)
82        .track_symbol(None)
83        .thumb_symbol("▌")
84        .render(area, buf, &mut scrollbar_state);
85}
examples/demo2/tabs/email.rs (line 119)
82fn render_inbox(selected_index: usize, area: Rect, buf: &mut Buffer) {
83    let vertical = Layout::vertical([Constraint::Length(1), Constraint::Min(0)]);
84    let [tabs, inbox] = vertical.areas(area);
85    let theme = THEME.email;
86    Tabs::new(vec![" Inbox ", " Sent ", " Drafts "])
87        .style(theme.tabs)
88        .highlight_style(theme.tabs_selected)
89        .select(0)
90        .divider("")
91        .render(tabs, buf);
92
93    let highlight_symbol = ">>";
94    let from_width = EMAILS
95        .iter()
96        .map(|e| e.from.width())
97        .max()
98        .unwrap_or_default();
99    let items = EMAILS.iter().map(|e| {
100        let from = format!("{:width$}", e.from, width = from_width).into();
101        ListItem::new(Line::from(vec![from, " ".into(), e.subject.into()]))
102    });
103    let mut state = ListState::default().with_selected(Some(selected_index));
104    StatefulWidget::render(
105        List::new(items)
106            .style(theme.inbox)
107            .highlight_style(theme.selected_item)
108            .highlight_symbol(highlight_symbol),
109        inbox,
110        buf,
111        &mut state,
112    );
113    let mut scrollbar_state = ScrollbarState::default()
114        .content_length(EMAILS.len())
115        .position(selected_index);
116    Scrollbar::default()
117        .begin_symbol(None)
118        .end_symbol(None)
119        .track_symbol(None)
120        .thumb_symbol("▐")
121        .render(inbox, buf, &mut scrollbar_state);
122}
examples/scrollbar.rs (line 166)
92    fn draw(&mut self, frame: &mut Frame) {
93        let area = frame.area();
94
95        // Words made "loooong" to demonstrate line breaking.
96        let s =
97            "Veeeeeeeeeeeeeeeery    loooooooooooooooooong   striiiiiiiiiiiiiiiiiiiiiiiiiing.   ";
98        let mut long_line = s.repeat(usize::from(area.width) / s.len() + 4);
99        long_line.push('\n');
100
101        let chunks = Layout::vertical([
102            Constraint::Min(1),
103            Constraint::Percentage(25),
104            Constraint::Percentage(25),
105            Constraint::Percentage(25),
106            Constraint::Percentage(25),
107        ])
108        .split(area);
109
110        let text = vec![
111            Line::from("This is a line "),
112            Line::from("This is a line   ".red()),
113            Line::from("This is a line".on_dark_gray()),
114            Line::from("This is a longer line".crossed_out()),
115            Line::from(long_line.clone()),
116            Line::from("This is a line".reset()),
117            Line::from(vec![
118                Span::raw("Masked text: "),
119                Span::styled(Masked::new("password", '*'), Style::new().fg(Color::Red)),
120            ]),
121            Line::from("This is a line "),
122            Line::from("This is a line   ".red()),
123            Line::from("This is a line".on_dark_gray()),
124            Line::from("This is a longer line".crossed_out()),
125            Line::from(long_line.clone()),
126            Line::from("This is a line".reset()),
127            Line::from(vec![
128                Span::raw("Masked text: "),
129                Span::styled(Masked::new("password", '*'), Style::new().fg(Color::Red)),
130            ]),
131        ];
132        self.vertical_scroll_state = self.vertical_scroll_state.content_length(text.len());
133        self.horizontal_scroll_state = self.horizontal_scroll_state.content_length(long_line.len());
134
135        let create_block = |title: &'static str| Block::bordered().gray().title(title.bold());
136
137        let title = Block::new()
138            .title_alignment(Alignment::Center)
139            .title("Use h j k l or ◄ ▲ ▼ ► to scroll ".bold());
140        frame.render_widget(title, chunks[0]);
141
142        let paragraph = Paragraph::new(text.clone())
143            .gray()
144            .block(create_block("Vertical scrollbar with arrows"))
145            .scroll((self.vertical_scroll as u16, 0));
146        frame.render_widget(paragraph, chunks[1]);
147        frame.render_stateful_widget(
148            Scrollbar::new(ScrollbarOrientation::VerticalRight)
149                .begin_symbol(Some("↑"))
150                .end_symbol(Some("↓")),
151            chunks[1],
152            &mut self.vertical_scroll_state,
153        );
154
155        let paragraph = Paragraph::new(text.clone())
156            .gray()
157            .block(create_block(
158                "Vertical scrollbar without arrows, without track symbol and mirrored",
159            ))
160            .scroll((self.vertical_scroll as u16, 0));
161        frame.render_widget(paragraph, chunks[2]);
162        frame.render_stateful_widget(
163            Scrollbar::new(ScrollbarOrientation::VerticalLeft)
164                .symbols(scrollbar::VERTICAL)
165                .begin_symbol(None)
166                .track_symbol(None)
167                .end_symbol(None),
168            chunks[2].inner(Margin {
169                vertical: 1,
170                horizontal: 0,
171            }),
172            &mut self.vertical_scroll_state,
173        );
174
175        let paragraph = Paragraph::new(text.clone())
176            .gray()
177            .block(create_block(
178                "Horizontal scrollbar with only begin arrow & custom thumb symbol",
179            ))
180            .scroll((0, self.horizontal_scroll as u16));
181        frame.render_widget(paragraph, chunks[3]);
182        frame.render_stateful_widget(
183            Scrollbar::new(ScrollbarOrientation::HorizontalBottom)
184                .thumb_symbol("🬋")
185                .end_symbol(None),
186            chunks[3].inner(Margin {
187                vertical: 0,
188                horizontal: 1,
189            }),
190            &mut self.horizontal_scroll_state,
191        );
192
193        let paragraph = Paragraph::new(text.clone())
194            .gray()
195            .block(create_block(
196                "Horizontal scrollbar without arrows & custom thumb and track symbol",
197            ))
198            .scroll((0, self.horizontal_scroll as u16));
199        frame.render_widget(paragraph, chunks[4]);
200        frame.render_stateful_widget(
201            Scrollbar::new(ScrollbarOrientation::HorizontalBottom)
202                .thumb_symbol("░")
203                .track_symbol(Some("─")),
204            chunks[4].inner(Margin {
205                vertical: 0,
206                horizontal: 1,
207            }),
208            &mut self.horizontal_scroll_state,
209        );
210    }
Source

pub fn track_style<S: Into<Style>>(self, track_style: S) -> Self

Sets the style that is used for the track of the scrollbar.

See Scrollbar for a visual example of what this represents.

style accepts any type that is convertible to Style (e.g. Style, Color, or your own type that implements Into<Style>).

This is a fluent setter method which must be chained or used as it consumes self

Source

pub const fn begin_symbol(self, begin_symbol: Option<&'a str>) -> Self

Sets the symbol that represents the beginning of the scrollbar.

See Scrollbar for a visual example of what this represents.

This is a fluent setter method which must be chained or used as it consumes self

Examples found in repository?
examples/demo2/tabs/recipe.rs (line 180)
174fn render_scrollbar(position: usize, area: Rect, buf: &mut Buffer) {
175    let mut state = ScrollbarState::default()
176        .content_length(INGREDIENTS.len())
177        .viewport_content_length(6)
178        .position(position);
179    Scrollbar::new(ScrollbarOrientation::VerticalRight)
180        .begin_symbol(None)
181        .end_symbol(None)
182        .track_symbol(None)
183        .thumb_symbol("▐")
184        .render(area, buf, &mut state);
185}
More examples
Hide additional examples
examples/table.rs (line 273)
269    fn render_scrollbar(&mut self, frame: &mut Frame, area: Rect) {
270        frame.render_stateful_widget(
271            Scrollbar::default()
272                .orientation(ScrollbarOrientation::VerticalRight)
273                .begin_symbol(None)
274                .end_symbol(None),
275            area.inner(Margin {
276                vertical: 1,
277                horizontal: 1,
278            }),
279            &mut self.scroll_state,
280        );
281    }
examples/demo2/tabs/traceroute.rs (line 80)
53fn render_hops(selected_row: usize, area: Rect, buf: &mut Buffer) {
54    let mut state = TableState::default().with_selected(Some(selected_row));
55    let rows = HOPS.iter().map(|hop| Row::new(vec![hop.host, hop.address]));
56    let block = Block::new()
57        .padding(Padding::new(1, 1, 1, 1))
58        .title_alignment(Alignment::Center)
59        .title("Traceroute bad.horse".bold().white());
60    StatefulWidget::render(
61        Table::new(rows, [Constraint::Max(100), Constraint::Length(15)])
62            .header(Row::new(vec!["Host", "Address"]).set_style(THEME.traceroute.header))
63            .row_highlight_style(THEME.traceroute.selected)
64            .block(block),
65        area,
66        buf,
67        &mut state,
68    );
69    let mut scrollbar_state = ScrollbarState::default()
70        .content_length(HOPS.len())
71        .position(selected_row);
72    let area = Rect {
73        width: area.width + 1,
74        y: area.y + 3,
75        height: area.height - 4,
76        ..area
77    };
78    Scrollbar::default()
79        .orientation(ScrollbarOrientation::VerticalLeft)
80        .begin_symbol(None)
81        .end_symbol(None)
82        .track_symbol(None)
83        .thumb_symbol("▌")
84        .render(area, buf, &mut scrollbar_state);
85}
examples/demo2/tabs/email.rs (line 117)
82fn render_inbox(selected_index: usize, area: Rect, buf: &mut Buffer) {
83    let vertical = Layout::vertical([Constraint::Length(1), Constraint::Min(0)]);
84    let [tabs, inbox] = vertical.areas(area);
85    let theme = THEME.email;
86    Tabs::new(vec![" Inbox ", " Sent ", " Drafts "])
87        .style(theme.tabs)
88        .highlight_style(theme.tabs_selected)
89        .select(0)
90        .divider("")
91        .render(tabs, buf);
92
93    let highlight_symbol = ">>";
94    let from_width = EMAILS
95        .iter()
96        .map(|e| e.from.width())
97        .max()
98        .unwrap_or_default();
99    let items = EMAILS.iter().map(|e| {
100        let from = format!("{:width$}", e.from, width = from_width).into();
101        ListItem::new(Line::from(vec![from, " ".into(), e.subject.into()]))
102    });
103    let mut state = ListState::default().with_selected(Some(selected_index));
104    StatefulWidget::render(
105        List::new(items)
106            .style(theme.inbox)
107            .highlight_style(theme.selected_item)
108            .highlight_symbol(highlight_symbol),
109        inbox,
110        buf,
111        &mut state,
112    );
113    let mut scrollbar_state = ScrollbarState::default()
114        .content_length(EMAILS.len())
115        .position(selected_index);
116    Scrollbar::default()
117        .begin_symbol(None)
118        .end_symbol(None)
119        .track_symbol(None)
120        .thumb_symbol("▐")
121        .render(inbox, buf, &mut scrollbar_state);
122}
examples/scrollbar.rs (line 149)
92    fn draw(&mut self, frame: &mut Frame) {
93        let area = frame.area();
94
95        // Words made "loooong" to demonstrate line breaking.
96        let s =
97            "Veeeeeeeeeeeeeeeery    loooooooooooooooooong   striiiiiiiiiiiiiiiiiiiiiiiiiing.   ";
98        let mut long_line = s.repeat(usize::from(area.width) / s.len() + 4);
99        long_line.push('\n');
100
101        let chunks = Layout::vertical([
102            Constraint::Min(1),
103            Constraint::Percentage(25),
104            Constraint::Percentage(25),
105            Constraint::Percentage(25),
106            Constraint::Percentage(25),
107        ])
108        .split(area);
109
110        let text = vec![
111            Line::from("This is a line "),
112            Line::from("This is a line   ".red()),
113            Line::from("This is a line".on_dark_gray()),
114            Line::from("This is a longer line".crossed_out()),
115            Line::from(long_line.clone()),
116            Line::from("This is a line".reset()),
117            Line::from(vec![
118                Span::raw("Masked text: "),
119                Span::styled(Masked::new("password", '*'), Style::new().fg(Color::Red)),
120            ]),
121            Line::from("This is a line "),
122            Line::from("This is a line   ".red()),
123            Line::from("This is a line".on_dark_gray()),
124            Line::from("This is a longer line".crossed_out()),
125            Line::from(long_line.clone()),
126            Line::from("This is a line".reset()),
127            Line::from(vec![
128                Span::raw("Masked text: "),
129                Span::styled(Masked::new("password", '*'), Style::new().fg(Color::Red)),
130            ]),
131        ];
132        self.vertical_scroll_state = self.vertical_scroll_state.content_length(text.len());
133        self.horizontal_scroll_state = self.horizontal_scroll_state.content_length(long_line.len());
134
135        let create_block = |title: &'static str| Block::bordered().gray().title(title.bold());
136
137        let title = Block::new()
138            .title_alignment(Alignment::Center)
139            .title("Use h j k l or ◄ ▲ ▼ ► to scroll ".bold());
140        frame.render_widget(title, chunks[0]);
141
142        let paragraph = Paragraph::new(text.clone())
143            .gray()
144            .block(create_block("Vertical scrollbar with arrows"))
145            .scroll((self.vertical_scroll as u16, 0));
146        frame.render_widget(paragraph, chunks[1]);
147        frame.render_stateful_widget(
148            Scrollbar::new(ScrollbarOrientation::VerticalRight)
149                .begin_symbol(Some("↑"))
150                .end_symbol(Some("↓")),
151            chunks[1],
152            &mut self.vertical_scroll_state,
153        );
154
155        let paragraph = Paragraph::new(text.clone())
156            .gray()
157            .block(create_block(
158                "Vertical scrollbar without arrows, without track symbol and mirrored",
159            ))
160            .scroll((self.vertical_scroll as u16, 0));
161        frame.render_widget(paragraph, chunks[2]);
162        frame.render_stateful_widget(
163            Scrollbar::new(ScrollbarOrientation::VerticalLeft)
164                .symbols(scrollbar::VERTICAL)
165                .begin_symbol(None)
166                .track_symbol(None)
167                .end_symbol(None),
168            chunks[2].inner(Margin {
169                vertical: 1,
170                horizontal: 0,
171            }),
172            &mut self.vertical_scroll_state,
173        );
174
175        let paragraph = Paragraph::new(text.clone())
176            .gray()
177            .block(create_block(
178                "Horizontal scrollbar with only begin arrow & custom thumb symbol",
179            ))
180            .scroll((0, self.horizontal_scroll as u16));
181        frame.render_widget(paragraph, chunks[3]);
182        frame.render_stateful_widget(
183            Scrollbar::new(ScrollbarOrientation::HorizontalBottom)
184                .thumb_symbol("🬋")
185                .end_symbol(None),
186            chunks[3].inner(Margin {
187                vertical: 0,
188                horizontal: 1,
189            }),
190            &mut self.horizontal_scroll_state,
191        );
192
193        let paragraph = Paragraph::new(text.clone())
194            .gray()
195            .block(create_block(
196                "Horizontal scrollbar without arrows & custom thumb and track symbol",
197            ))
198            .scroll((0, self.horizontal_scroll as u16));
199        frame.render_widget(paragraph, chunks[4]);
200        frame.render_stateful_widget(
201            Scrollbar::new(ScrollbarOrientation::HorizontalBottom)
202                .thumb_symbol("░")
203                .track_symbol(Some("─")),
204            chunks[4].inner(Margin {
205                vertical: 0,
206                horizontal: 1,
207            }),
208            &mut self.horizontal_scroll_state,
209        );
210    }
Source

pub fn begin_style<S: Into<Style>>(self, begin_style: S) -> Self

Sets the style that is used for the beginning of the scrollbar.

See Scrollbar for a visual example of what this represents.

style accepts any type that is convertible to Style (e.g. Style, Color, or your own type that implements Into<Style>).

This is a fluent setter method which must be chained or used as it consumes self

Source

pub const fn end_symbol(self, end_symbol: Option<&'a str>) -> Self

Sets the symbol that represents the end of the scrollbar.

See Scrollbar for a visual example of what this represents.

This is a fluent setter method which must be chained or used as it consumes self

Examples found in repository?
examples/demo2/tabs/recipe.rs (line 181)
174fn render_scrollbar(position: usize, area: Rect, buf: &mut Buffer) {
175    let mut state = ScrollbarState::default()
176        .content_length(INGREDIENTS.len())
177        .viewport_content_length(6)
178        .position(position);
179    Scrollbar::new(ScrollbarOrientation::VerticalRight)
180        .begin_symbol(None)
181        .end_symbol(None)
182        .track_symbol(None)
183        .thumb_symbol("▐")
184        .render(area, buf, &mut state);
185}
More examples
Hide additional examples
examples/table.rs (line 274)
269    fn render_scrollbar(&mut self, frame: &mut Frame, area: Rect) {
270        frame.render_stateful_widget(
271            Scrollbar::default()
272                .orientation(ScrollbarOrientation::VerticalRight)
273                .begin_symbol(None)
274                .end_symbol(None),
275            area.inner(Margin {
276                vertical: 1,
277                horizontal: 1,
278            }),
279            &mut self.scroll_state,
280        );
281    }
examples/demo2/tabs/traceroute.rs (line 81)
53fn render_hops(selected_row: usize, area: Rect, buf: &mut Buffer) {
54    let mut state = TableState::default().with_selected(Some(selected_row));
55    let rows = HOPS.iter().map(|hop| Row::new(vec![hop.host, hop.address]));
56    let block = Block::new()
57        .padding(Padding::new(1, 1, 1, 1))
58        .title_alignment(Alignment::Center)
59        .title("Traceroute bad.horse".bold().white());
60    StatefulWidget::render(
61        Table::new(rows, [Constraint::Max(100), Constraint::Length(15)])
62            .header(Row::new(vec!["Host", "Address"]).set_style(THEME.traceroute.header))
63            .row_highlight_style(THEME.traceroute.selected)
64            .block(block),
65        area,
66        buf,
67        &mut state,
68    );
69    let mut scrollbar_state = ScrollbarState::default()
70        .content_length(HOPS.len())
71        .position(selected_row);
72    let area = Rect {
73        width: area.width + 1,
74        y: area.y + 3,
75        height: area.height - 4,
76        ..area
77    };
78    Scrollbar::default()
79        .orientation(ScrollbarOrientation::VerticalLeft)
80        .begin_symbol(None)
81        .end_symbol(None)
82        .track_symbol(None)
83        .thumb_symbol("▌")
84        .render(area, buf, &mut scrollbar_state);
85}
examples/demo2/tabs/email.rs (line 118)
82fn render_inbox(selected_index: usize, area: Rect, buf: &mut Buffer) {
83    let vertical = Layout::vertical([Constraint::Length(1), Constraint::Min(0)]);
84    let [tabs, inbox] = vertical.areas(area);
85    let theme = THEME.email;
86    Tabs::new(vec![" Inbox ", " Sent ", " Drafts "])
87        .style(theme.tabs)
88        .highlight_style(theme.tabs_selected)
89        .select(0)
90        .divider("")
91        .render(tabs, buf);
92
93    let highlight_symbol = ">>";
94    let from_width = EMAILS
95        .iter()
96        .map(|e| e.from.width())
97        .max()
98        .unwrap_or_default();
99    let items = EMAILS.iter().map(|e| {
100        let from = format!("{:width$}", e.from, width = from_width).into();
101        ListItem::new(Line::from(vec![from, " ".into(), e.subject.into()]))
102    });
103    let mut state = ListState::default().with_selected(Some(selected_index));
104    StatefulWidget::render(
105        List::new(items)
106            .style(theme.inbox)
107            .highlight_style(theme.selected_item)
108            .highlight_symbol(highlight_symbol),
109        inbox,
110        buf,
111        &mut state,
112    );
113    let mut scrollbar_state = ScrollbarState::default()
114        .content_length(EMAILS.len())
115        .position(selected_index);
116    Scrollbar::default()
117        .begin_symbol(None)
118        .end_symbol(None)
119        .track_symbol(None)
120        .thumb_symbol("▐")
121        .render(inbox, buf, &mut scrollbar_state);
122}
examples/scrollbar.rs (line 150)
92    fn draw(&mut self, frame: &mut Frame) {
93        let area = frame.area();
94
95        // Words made "loooong" to demonstrate line breaking.
96        let s =
97            "Veeeeeeeeeeeeeeeery    loooooooooooooooooong   striiiiiiiiiiiiiiiiiiiiiiiiiing.   ";
98        let mut long_line = s.repeat(usize::from(area.width) / s.len() + 4);
99        long_line.push('\n');
100
101        let chunks = Layout::vertical([
102            Constraint::Min(1),
103            Constraint::Percentage(25),
104            Constraint::Percentage(25),
105            Constraint::Percentage(25),
106            Constraint::Percentage(25),
107        ])
108        .split(area);
109
110        let text = vec![
111            Line::from("This is a line "),
112            Line::from("This is a line   ".red()),
113            Line::from("This is a line".on_dark_gray()),
114            Line::from("This is a longer line".crossed_out()),
115            Line::from(long_line.clone()),
116            Line::from("This is a line".reset()),
117            Line::from(vec![
118                Span::raw("Masked text: "),
119                Span::styled(Masked::new("password", '*'), Style::new().fg(Color::Red)),
120            ]),
121            Line::from("This is a line "),
122            Line::from("This is a line   ".red()),
123            Line::from("This is a line".on_dark_gray()),
124            Line::from("This is a longer line".crossed_out()),
125            Line::from(long_line.clone()),
126            Line::from("This is a line".reset()),
127            Line::from(vec![
128                Span::raw("Masked text: "),
129                Span::styled(Masked::new("password", '*'), Style::new().fg(Color::Red)),
130            ]),
131        ];
132        self.vertical_scroll_state = self.vertical_scroll_state.content_length(text.len());
133        self.horizontal_scroll_state = self.horizontal_scroll_state.content_length(long_line.len());
134
135        let create_block = |title: &'static str| Block::bordered().gray().title(title.bold());
136
137        let title = Block::new()
138            .title_alignment(Alignment::Center)
139            .title("Use h j k l or ◄ ▲ ▼ ► to scroll ".bold());
140        frame.render_widget(title, chunks[0]);
141
142        let paragraph = Paragraph::new(text.clone())
143            .gray()
144            .block(create_block("Vertical scrollbar with arrows"))
145            .scroll((self.vertical_scroll as u16, 0));
146        frame.render_widget(paragraph, chunks[1]);
147        frame.render_stateful_widget(
148            Scrollbar::new(ScrollbarOrientation::VerticalRight)
149                .begin_symbol(Some("↑"))
150                .end_symbol(Some("↓")),
151            chunks[1],
152            &mut self.vertical_scroll_state,
153        );
154
155        let paragraph = Paragraph::new(text.clone())
156            .gray()
157            .block(create_block(
158                "Vertical scrollbar without arrows, without track symbol and mirrored",
159            ))
160            .scroll((self.vertical_scroll as u16, 0));
161        frame.render_widget(paragraph, chunks[2]);
162        frame.render_stateful_widget(
163            Scrollbar::new(ScrollbarOrientation::VerticalLeft)
164                .symbols(scrollbar::VERTICAL)
165                .begin_symbol(None)
166                .track_symbol(None)
167                .end_symbol(None),
168            chunks[2].inner(Margin {
169                vertical: 1,
170                horizontal: 0,
171            }),
172            &mut self.vertical_scroll_state,
173        );
174
175        let paragraph = Paragraph::new(text.clone())
176            .gray()
177            .block(create_block(
178                "Horizontal scrollbar with only begin arrow & custom thumb symbol",
179            ))
180            .scroll((0, self.horizontal_scroll as u16));
181        frame.render_widget(paragraph, chunks[3]);
182        frame.render_stateful_widget(
183            Scrollbar::new(ScrollbarOrientation::HorizontalBottom)
184                .thumb_symbol("🬋")
185                .end_symbol(None),
186            chunks[3].inner(Margin {
187                vertical: 0,
188                horizontal: 1,
189            }),
190            &mut self.horizontal_scroll_state,
191        );
192
193        let paragraph = Paragraph::new(text.clone())
194            .gray()
195            .block(create_block(
196                "Horizontal scrollbar without arrows & custom thumb and track symbol",
197            ))
198            .scroll((0, self.horizontal_scroll as u16));
199        frame.render_widget(paragraph, chunks[4]);
200        frame.render_stateful_widget(
201            Scrollbar::new(ScrollbarOrientation::HorizontalBottom)
202                .thumb_symbol("░")
203                .track_symbol(Some("─")),
204            chunks[4].inner(Margin {
205                vertical: 0,
206                horizontal: 1,
207            }),
208            &mut self.horizontal_scroll_state,
209        );
210    }
Source

pub fn end_style<S: Into<Style>>(self, end_style: S) -> Self

Sets the style that is used for the end of the scrollbar.

See Scrollbar for a visual example of what this represents.

style accepts any type that is convertible to Style (e.g. Style, Color, or your own type that implements Into<Style>).

This is a fluent setter method which must be chained or used as it consumes self

Source

pub const fn symbols(self, symbols: Set) -> Self

Sets the symbols used for the various parts of the scrollbar from a Set.

<--▮------->
^  ^   ^   ^
│  │   │   └ end
│  │   └──── track
│  └──────── thumb
└─────────── begin

Only sets begin_symbol, end_symbol and track_symbol if they already contain a value. If they were set to None explicitly, this function will respect that choice. Use their respective setters to change their value.

This is a fluent setter method which must be chained or used as it consumes self

Examples found in repository?
examples/scrollbar.rs (line 164)
92    fn draw(&mut self, frame: &mut Frame) {
93        let area = frame.area();
94
95        // Words made "loooong" to demonstrate line breaking.
96        let s =
97            "Veeeeeeeeeeeeeeeery    loooooooooooooooooong   striiiiiiiiiiiiiiiiiiiiiiiiiing.   ";
98        let mut long_line = s.repeat(usize::from(area.width) / s.len() + 4);
99        long_line.push('\n');
100
101        let chunks = Layout::vertical([
102            Constraint::Min(1),
103            Constraint::Percentage(25),
104            Constraint::Percentage(25),
105            Constraint::Percentage(25),
106            Constraint::Percentage(25),
107        ])
108        .split(area);
109
110        let text = vec![
111            Line::from("This is a line "),
112            Line::from("This is a line   ".red()),
113            Line::from("This is a line".on_dark_gray()),
114            Line::from("This is a longer line".crossed_out()),
115            Line::from(long_line.clone()),
116            Line::from("This is a line".reset()),
117            Line::from(vec![
118                Span::raw("Masked text: "),
119                Span::styled(Masked::new("password", '*'), Style::new().fg(Color::Red)),
120            ]),
121            Line::from("This is a line "),
122            Line::from("This is a line   ".red()),
123            Line::from("This is a line".on_dark_gray()),
124            Line::from("This is a longer line".crossed_out()),
125            Line::from(long_line.clone()),
126            Line::from("This is a line".reset()),
127            Line::from(vec![
128                Span::raw("Masked text: "),
129                Span::styled(Masked::new("password", '*'), Style::new().fg(Color::Red)),
130            ]),
131        ];
132        self.vertical_scroll_state = self.vertical_scroll_state.content_length(text.len());
133        self.horizontal_scroll_state = self.horizontal_scroll_state.content_length(long_line.len());
134
135        let create_block = |title: &'static str| Block::bordered().gray().title(title.bold());
136
137        let title = Block::new()
138            .title_alignment(Alignment::Center)
139            .title("Use h j k l or ◄ ▲ ▼ ► to scroll ".bold());
140        frame.render_widget(title, chunks[0]);
141
142        let paragraph = Paragraph::new(text.clone())
143            .gray()
144            .block(create_block("Vertical scrollbar with arrows"))
145            .scroll((self.vertical_scroll as u16, 0));
146        frame.render_widget(paragraph, chunks[1]);
147        frame.render_stateful_widget(
148            Scrollbar::new(ScrollbarOrientation::VerticalRight)
149                .begin_symbol(Some("↑"))
150                .end_symbol(Some("↓")),
151            chunks[1],
152            &mut self.vertical_scroll_state,
153        );
154
155        let paragraph = Paragraph::new(text.clone())
156            .gray()
157            .block(create_block(
158                "Vertical scrollbar without arrows, without track symbol and mirrored",
159            ))
160            .scroll((self.vertical_scroll as u16, 0));
161        frame.render_widget(paragraph, chunks[2]);
162        frame.render_stateful_widget(
163            Scrollbar::new(ScrollbarOrientation::VerticalLeft)
164                .symbols(scrollbar::VERTICAL)
165                .begin_symbol(None)
166                .track_symbol(None)
167                .end_symbol(None),
168            chunks[2].inner(Margin {
169                vertical: 1,
170                horizontal: 0,
171            }),
172            &mut self.vertical_scroll_state,
173        );
174
175        let paragraph = Paragraph::new(text.clone())
176            .gray()
177            .block(create_block(
178                "Horizontal scrollbar with only begin arrow & custom thumb symbol",
179            ))
180            .scroll((0, self.horizontal_scroll as u16));
181        frame.render_widget(paragraph, chunks[3]);
182        frame.render_stateful_widget(
183            Scrollbar::new(ScrollbarOrientation::HorizontalBottom)
184                .thumb_symbol("🬋")
185                .end_symbol(None),
186            chunks[3].inner(Margin {
187                vertical: 0,
188                horizontal: 1,
189            }),
190            &mut self.horizontal_scroll_state,
191        );
192
193        let paragraph = Paragraph::new(text.clone())
194            .gray()
195            .block(create_block(
196                "Horizontal scrollbar without arrows & custom thumb and track symbol",
197            ))
198            .scroll((0, self.horizontal_scroll as u16));
199        frame.render_widget(paragraph, chunks[4]);
200        frame.render_stateful_widget(
201            Scrollbar::new(ScrollbarOrientation::HorizontalBottom)
202                .thumb_symbol("░")
203                .track_symbol(Some("─")),
204            chunks[4].inner(Margin {
205                vertical: 0,
206                horizontal: 1,
207            }),
208            &mut self.horizontal_scroll_state,
209        );
210    }
Source

pub fn style<S: Into<Style>>(self, style: S) -> Self

Sets the style used for the various parts of the scrollbar from a Style.

style accepts any type that is convertible to Style (e.g. Style, Color, or your own type that implements Into<Style>).

<--▮------->
^  ^   ^   ^
│  │   │   └ end
│  │   └──── track
│  └──────── thumb
└─────────── begin

This is a fluent setter method which must be chained or used as it consumes self

Trait Implementations§

Source§

impl<'a> Clone for Scrollbar<'a>

Source§

fn clone(&self) -> Scrollbar<'a>

Returns a copy of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl<'a> Debug for Scrollbar<'a>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<'a> Default for Scrollbar<'a>

Source§

fn default() -> Self

Returns the “default value” for a type. Read more
Source§

impl<'a> Hash for Scrollbar<'a>

Source§

fn hash<__H: Hasher>(&self, state: &mut __H)

Feeds this value into the given Hasher. Read more
1.3.0 · Source§

fn hash_slice<H>(data: &[Self], state: &mut H)
where H: Hasher, Self: Sized,

Feeds a slice of this type into the given Hasher. Read more
Source§

impl<'a> PartialEq for Scrollbar<'a>

Source§

fn eq(&self, other: &Scrollbar<'a>) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
Source§

impl<'a> StatefulWidget for Scrollbar<'a>

Source§

type State = ScrollbarState

State associated with the stateful widget. Read more
Source§

fn render(self, area: Rect, buf: &mut Buffer, state: &mut Self::State)

Draws the current state of the widget in the given buffer. That is the only method required to implement a custom stateful widget.
Source§

impl<'a> Eq for Scrollbar<'a>

Source§

impl<'a> StructuralPartialEq for Scrollbar<'a>

Auto Trait Implementations§

§

impl<'a> Freeze for Scrollbar<'a>

§

impl<'a> RefUnwindSafe for Scrollbar<'a>

§

impl<'a> Send for Scrollbar<'a>

§

impl<'a> Sync for Scrollbar<'a>

§

impl<'a> Unpin for Scrollbar<'a>

§

impl<'a> UnwindSafe for Scrollbar<'a>

Blanket Implementations§

Source§

impl<S, D, Swp, Dwp, T> AdaptInto<D, Swp, Dwp, T> for S
where T: Real + Zero + Arithmetics + Clone, Swp: WhitePoint<T>, Dwp: WhitePoint<T>, D: AdaptFrom<S, Swp, Dwp, T>,

Source§

fn adapt_into_using<M>(self, method: M) -> D
where M: TransformMatrix<T>,

Convert the source color to the destination color using the specified method.
Source§

fn adapt_into(self) -> D

Convert the source color to the destination color using the bradford method by default.
Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T, C> ArraysFrom<C> for T
where C: IntoArrays<T>,

Source§

fn arrays_from(colors: C) -> T

Cast a collection of colors into a collection of arrays.
Source§

impl<T, C> ArraysInto<C> for T
where C: FromArrays<T>,

Source§

fn arrays_into(self) -> C

Cast this collection of arrays into a collection of colors.
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<WpParam, T, U> Cam16IntoUnclamped<WpParam, T> for U
where T: FromCam16Unclamped<WpParam, U>,

Source§

type Scalar = <T as FromCam16Unclamped<WpParam, U>>::Scalar

The number type that’s used in parameters when converting.
Source§

fn cam16_into_unclamped( self, parameters: BakedParameters<WpParam, <U as Cam16IntoUnclamped<WpParam, T>>::Scalar>, ) -> T

Converts self into C, using the provided parameters.
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T, C> ComponentsFrom<C> for T
where C: IntoComponents<T>,

Source§

fn components_from(colors: C) -> T

Cast a collection of colors into a collection of color components.
Source§

impl<Q, K> Equivalent<K> for Q
where Q: Eq + ?Sized, K: Borrow<Q> + ?Sized,

Source§

fn equivalent(&self, key: &K) -> bool

Compare self to key and return true if they are equal.
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> FromAngle<T> for T

Source§

fn from_angle(angle: T) -> T

Performs a conversion from angle.
Source§

impl<T, U> FromStimulus<U> for T
where U: IntoStimulus<T>,

Source§

fn from_stimulus(other: U) -> T

Converts other into Self, while performing the appropriate scaling, rounding and clamping.
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> IntoAngle<U> for T
where U: FromAngle<T>,

Source§

fn into_angle(self) -> U

Performs a conversion into T.
Source§

impl<WpParam, T, U> IntoCam16Unclamped<WpParam, T> for U
where T: Cam16FromUnclamped<WpParam, U>,

Source§

type Scalar = <T as Cam16FromUnclamped<WpParam, U>>::Scalar

The number type that’s used in parameters when converting.
Source§

fn into_cam16_unclamped( self, parameters: BakedParameters<WpParam, <U as IntoCam16Unclamped<WpParam, T>>::Scalar>, ) -> T

Converts self into C, using the provided parameters.
Source§

impl<T, U> IntoColor<U> for T
where U: FromColor<T>,

Source§

fn into_color(self) -> U

Convert into T with values clamped to the color defined bounds Read more
Source§

impl<T, U> IntoColorUnclamped<U> for T
where U: FromColorUnclamped<T>,

Source§

fn into_color_unclamped(self) -> U

Convert into T. The resulting color might be invalid in its color space Read more
Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<T> IntoStimulus<T> for T

Source§

fn into_stimulus(self) -> T

Converts self into T, while performing the appropriate scaling, rounding and clamping.
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, C> TryComponentsInto<C> for T
where C: TryFromComponents<T>,

Source§

type Error = <C as TryFromComponents<T>>::Error

The error for when try_into_colors fails to cast.
Source§

fn try_components_into(self) -> Result<C, <T as TryComponentsInto<C>>::Error>

Try to cast this collection of color components into a collection of colors. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T, U> TryIntoColor<U> for T
where U: TryFromColor<T>,

Source§

fn try_into_color(self) -> Result<U, OutOfBounds<U>>

Convert into T, returning ok if the color is inside of its defined range, otherwise an OutOfBounds error is returned which contains the unclamped color. Read more
Source§

impl<C, U> UintsFrom<C> for U
where C: IntoUints<U>,

Source§

fn uints_from(colors: C) -> U

Cast a collection of colors into a collection of unsigned integers.
Source§

impl<C, U> UintsInto<C> for U
where C: FromUints<U>,

Source§

fn uints_into(self) -> C

Cast this collection of unsigned integers into a collection of colors.