fix(tabs)!: set the default highlight_style (#635)

Previously the default highlight_style was set to `Style::default()`,
which meant that the highlight style was the same as the normal style.
This change sets the default highlight_style to reversed text.

BREAKING CHANGE: The `Tab` widget now renders the highlight style as
reversed text by default. This can be changed by setting the
`highlight_style` field of the `Tab` widget.
This commit is contained in:
Josh McKinney 2023-12-04 01:39:46 -08:00 committed by GitHub
parent 6a6e9dde9d
commit e4579f0db2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 57 additions and 30 deletions

View file

@ -11,8 +11,9 @@ github with a [breaking change] label.
This is a quick summary of the sections below:
- Unreleased (0.24.1)
-`Table::widths()` now accepts `AsRef<[Constraint]>`
- `Table::widths()` now accepts `AsRef<[Constraint]>`
- Layout::new() now accepts direction and constraint parameters
- The default `Tabs::highlight_style` is now `Style::new().reversed()`
- [v0.24.0](#v0240)
- MSRV is now 1.70.0
@ -38,6 +39,13 @@ This is a quick summary of the sections below:
## Unreleased (v0.24.1)
### The default `Tabs::highlight_style` is now `Style::new().reversed()` ([#635])
Previously the default highlight style for tabs was `Style::default()`, which meant that a `Tabs`
widget in the default configuration would not show any indication of the selected tab.
[#635]: https://github.com/ratatui-org/ratatui/pull/635
### `Table::widths()` now accepts `AsRef<[Constraint]>` ([#628])
[#628]: https://github.com/ratatui-org/ratatui/pull/628

View file

@ -2,12 +2,14 @@
use crate::{
buffer::Buffer,
layout::Rect,
style::{Style, Styled},
style::{Modifier, Style, Styled},
symbols,
text::{Line, Span},
widgets::{Block, Widget},
};
const DEFAULT_HIGHLIGHT_STYLE: Style = Style::new().add_modifier(Modifier::REVERSED);
/// A widget that displays a horizontal set of Tabs with a single tab selected.
///
/// Each tab title is stored as a [`Line`] which can be individually styled. The selected tab is set
@ -56,6 +58,18 @@ impl<'a> Tabs<'a> {
/// `titles` can be a [`Vec`] of [`&str`], [`String`] or anything that can be converted into
/// [`Line`]. As such, titles can be styled independently.
///
/// The selected tab can be set with [`Tabs::select`]. The first tab has index 0 (this is also
/// the default index).
///
/// The selected tab can have a different style with [`Tabs::highlight_style`]. This defaults to
/// a style with the [`Modifier::REVERSED`] modifier added.
///
/// The default divider is a pipe (`|`), but it can be customized with [`Tabs::divider`].
///
/// The entire widget can be styled with [`Tabs::style`].
///
/// The widget can be wrapped in a [`Block`] using [`Tabs::block`].
///
/// # Examples
///
/// Basic titles.
@ -78,7 +92,7 @@ impl<'a> Tabs<'a> {
titles: titles.into_iter().map(Into::into).collect(),
selected: 0,
style: Style::default(),
highlight_style: Style::default(),
highlight_style: DEFAULT_HIGHLIGHT_STYLE,
divider: Span::raw(symbols::line::VERTICAL),
padding_left: Line::from(" "),
padding_right: Line::from(" "),
@ -307,7 +321,7 @@ mod tests {
],
selected: 0,
style: Style::default(),
highlight_style: Style::default(),
highlight_style: DEFAULT_HIGHLIGHT_STYLE,
divider: Span::raw(symbols::line::VERTICAL),
padding_right: Line::from(" "),
padding_left: Line::from(" "),
@ -324,10 +338,10 @@ mod tests {
#[test]
fn render_default() {
let tabs = Tabs::new(vec!["Tab1", "Tab2", "Tab3", "Tab4"]);
assert_buffer_eq!(
render(tabs, Rect::new(0, 0, 30, 1)),
Buffer::with_lines(vec![" Tab1 │ Tab2 │ Tab3 │ Tab4 "])
);
let mut expected = Buffer::with_lines(vec![" Tab1 │ Tab2 │ Tab3 │ Tab4 "]);
// first tab selected
expected.set_style(Rect::new(1, 0, 4, 1), DEFAULT_HIGHLIGHT_STYLE);
assert_buffer_eq!(render(tabs, Rect::new(0, 0, 30, 1)), expected);
}
#[test]
@ -352,30 +366,28 @@ mod tests {
fn render_with_block() {
let tabs = Tabs::new(vec!["Tab1", "Tab2", "Tab3", "Tab4"])
.block(Block::default().title("Tabs").borders(Borders::ALL));
assert_buffer_eq!(
render(tabs, Rect::new(0, 0, 30, 3)),
Buffer::with_lines(vec![
"┌Tabs────────────────────────┐",
"│ Tab1 │ Tab2 │ Tab3 │ Tab4 │",
"└────────────────────────────┘",
])
);
let mut expected = Buffer::with_lines(vec![
"┌Tabs────────────────────────┐",
"│ Tab1 │ Tab2 │ Tab3 │ Tab4 │",
"└────────────────────────────┘",
]);
// first tab selected
expected.set_style(Rect::new(2, 1, 4, 1), DEFAULT_HIGHLIGHT_STYLE);
assert_buffer_eq!(render(tabs, Rect::new(0, 0, 30, 3)), expected);
}
#[test]
fn render_style() {
let tabs =
Tabs::new(vec!["Tab1", "Tab2", "Tab3", "Tab4"]).style(Style::default().fg(Color::Red));
assert_buffer_eq!(
render(tabs, Rect::new(0, 0, 30, 1)),
Buffer::with_lines(vec![" Tab1 │ Tab2 │ Tab3 │ Tab4 ".red()])
);
let mut expected = Buffer::with_lines(vec![" Tab1 │ Tab2 │ Tab3 │ Tab4 ".red()]);
expected.set_style(Rect::new(1, 0, 4, 1), DEFAULT_HIGHLIGHT_STYLE.red());
assert_buffer_eq!(render(tabs, Rect::new(0, 0, 30, 1)), expected);
}
#[test]
fn render_select() {
let tabs = Tabs::new(vec!["Tab1", "Tab2", "Tab3", "Tab4"])
.highlight_style(Style::new().reversed());
let tabs = Tabs::new(vec!["Tab1", "Tab2", "Tab3", "Tab4"]);
// first tab selected
assert_buffer_eq!(
@ -418,13 +430,13 @@ mod tests {
fn render_style_and_selected() {
let tabs = Tabs::new(vec!["Tab1", "Tab2", "Tab3", "Tab4"])
.style(Style::new().red())
.highlight_style(Style::new().reversed())
.highlight_style(Style::new().underlined())
.select(0);
assert_buffer_eq!(
render(tabs, Rect::new(0, 0, 30, 1)),
Buffer::with_lines(vec![Line::from(vec![
" ".red(),
"Tab1".red().reversed(),
"Tab1".red().underlined(),
" │ Tab2 │ Tab3 │ Tab4 ".red(),
])])
);
@ -433,10 +445,10 @@ mod tests {
#[test]
fn render_divider() {
let tabs = Tabs::new(vec!["Tab1", "Tab2", "Tab3", "Tab4"]).divider("--");
assert_buffer_eq!(
render(tabs, Rect::new(0, 0, 30, 1)),
Buffer::with_lines(vec![" Tab1 -- Tab2 -- Tab3 -- Tab4 ",])
);
let mut expected = Buffer::with_lines(vec![" Tab1 -- Tab2 -- Tab3 -- Tab4 "]);
// first tab selected
expected.set_style(Rect::new(1, 0, 4, 1), DEFAULT_HIGHLIGHT_STYLE);
assert_buffer_eq!(render(tabs, Rect::new(0, 0, 30, 1)), expected);
}
#[test]

View file

@ -1,5 +1,11 @@
use ratatui::{
backend::TestBackend, buffer::Buffer, layout::Rect, symbols, text::Line, widgets::Tabs,
backend::TestBackend,
buffer::Buffer,
layout::Rect,
style::{Style, Stylize},
symbols,
text::Line,
widgets::Tabs,
Terminal,
};
@ -43,6 +49,7 @@ fn widgets_tabs_should_truncate_the_last_item() {
);
})
.unwrap();
let expected = Buffer::with_lines(vec![format!(" Tab1 {} T ", symbols::line::VERTICAL)]);
let mut expected = Buffer::with_lines(vec![format!(" Tab1 {} T ", symbols::line::VERTICAL)]);
expected.set_style(Rect::new(1, 0, 4, 1), Style::new().reversed());
terminal.backend().assert_buffer(&expected);
}