Use accent border for TUI pane focus
This commit is contained in:
@@ -20,6 +20,7 @@ const MINIMUM_WIDTH: u16 = 40;
|
|||||||
const MINIMUM_HEIGHT: u16 = 8;
|
const MINIMUM_HEIGHT: u16 = 8;
|
||||||
const LARGE_OTP_HEIGHT: u16 = 8;
|
const LARGE_OTP_HEIGHT: u16 = 8;
|
||||||
const LARGE_OTP_ROWS: usize = 5;
|
const LARGE_OTP_ROWS: usize = 5;
|
||||||
|
const ACCENT_COLOR: Color = Color::Cyan;
|
||||||
const SELECTED_FOREGROUND: Color = Color::Black;
|
const SELECTED_FOREGROUND: Color = Color::Black;
|
||||||
const SELECTED_BACKGROUND: Color = Color::White;
|
const SELECTED_BACKGROUND: Color = Color::White;
|
||||||
|
|
||||||
@@ -71,7 +72,7 @@ pub fn draw(frame: &mut Frame, app: &App) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn draw_with_color_capability(frame: &mut Frame, app: &App, capability: ColorCapability) {
|
pub fn draw_with_color_capability(frame: &mut Frame, app: &App, capability: ColorCapability) {
|
||||||
draw_inner(frame, app);
|
draw_inner(frame, app, capability);
|
||||||
if capability == ColorCapability::Monochrome {
|
if capability == ColorCapability::Monochrome {
|
||||||
for cell in &mut frame.buffer_mut().content {
|
for cell in &mut frame.buffer_mut().content {
|
||||||
if cell.fg == SELECTED_FOREGROUND && cell.bg == SELECTED_BACKGROUND {
|
if cell.fg == SELECTED_FOREGROUND && cell.bg == SELECTED_BACKGROUND {
|
||||||
@@ -82,7 +83,7 @@ pub fn draw_with_color_capability(frame: &mut Frame, app: &App, capability: Colo
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn draw_inner(frame: &mut Frame, app: &App) {
|
fn draw_inner(frame: &mut Frame, app: &App, capability: ColorCapability) {
|
||||||
let area = frame.area();
|
let area = frame.area();
|
||||||
if layout_class(area) == LayoutClass::TooSmall {
|
if layout_class(area) == LayoutClass::TooSmall {
|
||||||
frame.render_widget(
|
frame.render_widget(
|
||||||
@@ -104,17 +105,17 @@ fn draw_inner(frame: &mut Frame, app: &App) {
|
|||||||
Constraint::Length(1),
|
Constraint::Length(1),
|
||||||
])
|
])
|
||||||
.split(area);
|
.split(area);
|
||||||
render_content(frame, app, rows[0]);
|
render_content(frame, app, rows[0], capability);
|
||||||
frame.render_widget(status_line(app), rows[1]);
|
frame.render_widget(status_line(app), rows[1]);
|
||||||
frame.render_widget(context_line(app), rows[2]);
|
frame.render_widget(context_line(app), rows[2]);
|
||||||
frame.render_widget(prompt_line(app), rows[3]);
|
frame.render_widget(prompt_line(app), rows[3]);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render_content(frame: &mut Frame, app: &App, area: Rect) {
|
fn render_content(frame: &mut Frame, app: &App, area: Rect, capability: ColorCapability) {
|
||||||
if app.mode() == Mode::Locked {
|
if app.mode() == Mode::Locked {
|
||||||
frame.render_widget(
|
frame.render_widget(
|
||||||
Paragraph::new("The password store is locked. Authentication is required.")
|
Paragraph::new("The password store is locked. Authentication is required.")
|
||||||
.block(Block::bordered().title("Locked"))
|
.block(pane_block("Locked", true, capability))
|
||||||
.wrap(Wrap { trim: true }),
|
.wrap(Wrap { trim: true }),
|
||||||
area,
|
area,
|
||||||
);
|
);
|
||||||
@@ -143,7 +144,11 @@ fn render_content(frame: &mut Frame, app: &App, area: Rect) {
|
|||||||
};
|
};
|
||||||
frame.render_widget(
|
frame.render_widget(
|
||||||
Paragraph::new(text)
|
Paragraph::new(text)
|
||||||
.block(Block::bordered().title(format!("{} — Esc closes", popup.title())))
|
.block(pane_block(
|
||||||
|
format!("{} — Esc closes", popup.title()),
|
||||||
|
true,
|
||||||
|
capability,
|
||||||
|
))
|
||||||
.wrap(Wrap { trim: false }),
|
.wrap(Wrap { trim: false }),
|
||||||
area,
|
area,
|
||||||
);
|
);
|
||||||
@@ -152,7 +157,7 @@ fn render_content(frame: &mut Frame, app: &App, area: Rect) {
|
|||||||
if let Some(uri) = app.uri_popup() {
|
if let Some(uri) = app.uri_popup() {
|
||||||
frame.render_widget(
|
frame.render_widget(
|
||||||
Paragraph::new(String::from_utf8_lossy(uri.expose()).into_owned())
|
Paragraph::new(String::from_utf8_lossy(uri.expose()).into_owned())
|
||||||
.block(Block::bordered().title("OTP URI — Esc closes"))
|
.block(pane_block("OTP URI — Esc closes", true, capability))
|
||||||
.wrap(Wrap { trim: false }),
|
.wrap(Wrap { trim: false }),
|
||||||
area,
|
area,
|
||||||
);
|
);
|
||||||
@@ -163,7 +168,7 @@ fn render_content(frame: &mut Frame, app: &App, area: Rect) {
|
|||||||
if let Some(help) = app.command_help() {
|
if let Some(help) = app.command_help() {
|
||||||
frame.render_widget(
|
frame.render_widget(
|
||||||
Paragraph::new(help)
|
Paragraph::new(help)
|
||||||
.block(Block::bordered().title("Command help"))
|
.block(pane_block("Command help", true, capability))
|
||||||
.wrap(Wrap { trim: false }),
|
.wrap(Wrap { trim: false }),
|
||||||
area,
|
area,
|
||||||
);
|
);
|
||||||
@@ -195,10 +200,11 @@ fn render_content(frame: &mut Frame, app: &App, area: Rect) {
|
|||||||
};
|
};
|
||||||
frame.render_widget(
|
frame.render_widget(
|
||||||
Paragraph::new(lines)
|
Paragraph::new(lines)
|
||||||
.block(Block::bordered().title(format!(
|
.block(pane_block(
|
||||||
"Contextual help — {}",
|
format!("Contextual help — {}", mode_title(app.help_context_mode())),
|
||||||
mode_title(app.help_context_mode())
|
true,
|
||||||
)))
|
capability,
|
||||||
|
))
|
||||||
.wrap(Wrap { trim: false }),
|
.wrap(Wrap { trim: false }),
|
||||||
area,
|
area,
|
||||||
);
|
);
|
||||||
@@ -210,7 +216,7 @@ fn render_content(frame: &mut Frame, app: &App, area: Rect) {
|
|||||||
{
|
{
|
||||||
frame.render_widget(
|
frame.render_widget(
|
||||||
Paragraph::new(workflow.rows().join("\n"))
|
Paragraph::new(workflow.rows().join("\n"))
|
||||||
.block(Block::bordered().title(workflow.title()))
|
.block(pane_block(workflow.title(), true, capability))
|
||||||
.wrap(Wrap { trim: false }),
|
.wrap(Wrap { trim: false }),
|
||||||
area,
|
area,
|
||||||
);
|
);
|
||||||
@@ -240,7 +246,11 @@ fn render_content(frame: &mut Frame, app: &App, area: Rect) {
|
|||||||
let panes = Layout::new(direction, constraints).split(area);
|
let panes = Layout::new(direction, constraints).split(area);
|
||||||
frame.render_widget(
|
frame.render_widget(
|
||||||
Paragraph::new(sidebar_lines(app))
|
Paragraph::new(sidebar_lines(app))
|
||||||
.block(pane_block("Passwords", app.focus() == PaneFocus::Sidebar))
|
.block(pane_block(
|
||||||
|
"Passwords",
|
||||||
|
app.focus() == PaneFocus::Sidebar,
|
||||||
|
capability,
|
||||||
|
))
|
||||||
.wrap(Wrap { trim: false }),
|
.wrap(Wrap { trim: false }),
|
||||||
panes[0],
|
panes[0],
|
||||||
);
|
);
|
||||||
@@ -255,6 +265,8 @@ fn render_content(frame: &mut Frame, app: &App, area: Rect) {
|
|||||||
frame,
|
frame,
|
||||||
app.otp_display().expect("large OTP was checked"),
|
app.otp_display().expect("large OTP was checked"),
|
||||||
main_rows[0],
|
main_rows[0],
|
||||||
|
app.focus() == PaneFocus::Main,
|
||||||
|
capability,
|
||||||
);
|
);
|
||||||
let lines = viewer_lines(viewer, None);
|
let lines = viewer_lines(viewer, None);
|
||||||
let scroll = viewer_scroll(viewer, &lines, main_rows[1]);
|
let scroll = viewer_scroll(viewer, &lines, main_rows[1]);
|
||||||
@@ -264,6 +276,7 @@ fn render_content(frame: &mut Frame, app: &App, area: Rect) {
|
|||||||
.block(pane_block(
|
.block(pane_block(
|
||||||
mode_title(app.mode()),
|
mode_title(app.mode()),
|
||||||
app.focus() == PaneFocus::Main,
|
app.focus() == PaneFocus::Main,
|
||||||
|
capability,
|
||||||
))
|
))
|
||||||
.wrap(Wrap { trim: false }),
|
.wrap(Wrap { trim: false }),
|
||||||
main_rows[1],
|
main_rows[1],
|
||||||
@@ -282,7 +295,13 @@ fn render_content(frame: &mut Frame, app: &App, area: Rect) {
|
|||||||
(panes[1], None)
|
(panes[1], None)
|
||||||
};
|
};
|
||||||
if let Some(details_area) = details_area {
|
if let Some(details_area) = details_area {
|
||||||
render_compact_otp(frame, display, otp_area);
|
render_compact_otp(
|
||||||
|
frame,
|
||||||
|
display,
|
||||||
|
otp_area,
|
||||||
|
app.focus() == PaneFocus::Main,
|
||||||
|
capability,
|
||||||
|
);
|
||||||
let lines = viewer_lines(viewer, None);
|
let lines = viewer_lines(viewer, None);
|
||||||
let scroll = viewer_scroll(viewer, &lines, details_area);
|
let scroll = viewer_scroll(viewer, &lines, details_area);
|
||||||
frame.render_widget(
|
frame.render_widget(
|
||||||
@@ -291,12 +310,13 @@ fn render_content(frame: &mut Frame, app: &App, area: Rect) {
|
|||||||
.block(pane_block(
|
.block(pane_block(
|
||||||
mode_title(app.mode()),
|
mode_title(app.mode()),
|
||||||
app.focus() == PaneFocus::Main,
|
app.focus() == PaneFocus::Main,
|
||||||
|
capability,
|
||||||
))
|
))
|
||||||
.wrap(Wrap { trim: false }),
|
.wrap(Wrap { trim: false }),
|
||||||
details_area,
|
details_area,
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
render_compact_viewer(frame, app, viewer, display, otp_area);
|
render_compact_viewer(frame, app, viewer, display, otp_area, capability);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -330,6 +350,7 @@ fn render_content(frame: &mut Frame, app: &App, area: Rect) {
|
|||||||
main.block(pane_block(
|
main.block(pane_block(
|
||||||
mode_title(app.mode()),
|
mode_title(app.mode()),
|
||||||
app.focus() == PaneFocus::Main,
|
app.focus() == PaneFocus::Main,
|
||||||
|
capability,
|
||||||
))
|
))
|
||||||
.wrap(Wrap { trim: false }),
|
.wrap(Wrap { trim: false }),
|
||||||
panes[1],
|
panes[1],
|
||||||
@@ -374,7 +395,13 @@ fn matching_totp_display<'a>(
|
|||||||
.then_some(display)
|
.then_some(display)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render_large_otp(frame: &mut Frame, display: &crate::app::OtpDisplay, area: Rect) {
|
fn render_large_otp(
|
||||||
|
frame: &mut Frame,
|
||||||
|
display: &crate::app::OtpDisplay,
|
||||||
|
area: Rect,
|
||||||
|
focused: bool,
|
||||||
|
capability: ColorCapability,
|
||||||
|
) {
|
||||||
let glyphs = (0..LARGE_OTP_ROWS)
|
let glyphs = (0..LARGE_OTP_ROWS)
|
||||||
.map(|row| otp_ascii_row(display.code().expose(), row))
|
.map(|row| otp_ascii_row(display.code().expose(), row))
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
@@ -394,21 +421,31 @@ fn render_large_otp(frame: &mut Frame, display: &crate::app::OtpDisplay, area: R
|
|||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
lines.push(Line::styled(
|
lines.push(Line::styled(
|
||||||
countdown_bar(remaining, period, inner_width),
|
countdown_bar(remaining, period, inner_width),
|
||||||
Style::default().fg(Color::Cyan),
|
Style::default().fg(ACCENT_COLOR),
|
||||||
));
|
));
|
||||||
frame.render_widget(
|
frame.render_widget(
|
||||||
Paragraph::new(lines)
|
Paragraph::new(lines)
|
||||||
.alignment(Alignment::Center)
|
.alignment(Alignment::Center)
|
||||||
.block(Block::bordered().title(format!("TOTP code — {remaining}s remaining"))),
|
.block(pane_block(
|
||||||
|
format!("TOTP code — {remaining}s remaining"),
|
||||||
|
focused,
|
||||||
|
capability,
|
||||||
|
)),
|
||||||
area,
|
area,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render_compact_otp(frame: &mut Frame, display: &crate::app::OtpDisplay, area: Rect) {
|
fn render_compact_otp(
|
||||||
|
frame: &mut Frame,
|
||||||
|
display: &crate::app::OtpDisplay,
|
||||||
|
area: Rect,
|
||||||
|
focused: bool,
|
||||||
|
capability: ColorCapability,
|
||||||
|
) {
|
||||||
frame.render_widget(
|
frame.render_widget(
|
||||||
Paragraph::new(compact_otp_line(display))
|
Paragraph::new(compact_otp_line(display))
|
||||||
.alignment(Alignment::Center)
|
.alignment(Alignment::Center)
|
||||||
.block(Block::bordered().title("TOTP code")),
|
.block(pane_block("TOTP code", focused, capability)),
|
||||||
area,
|
area,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -433,9 +470,14 @@ fn render_compact_viewer(
|
|||||||
viewer: &EntryViewer,
|
viewer: &EntryViewer,
|
||||||
display: &crate::app::OtpDisplay,
|
display: &crate::app::OtpDisplay,
|
||||||
area: Rect,
|
area: Rect,
|
||||||
|
capability: ColorCapability,
|
||||||
) {
|
) {
|
||||||
frame.render_widget(
|
frame.render_widget(
|
||||||
pane_block(mode_title(app.mode()), app.focus() == PaneFocus::Main),
|
pane_block(
|
||||||
|
mode_title(app.mode()),
|
||||||
|
app.focus() == PaneFocus::Main,
|
||||||
|
capability,
|
||||||
|
),
|
||||||
area,
|
area,
|
||||||
);
|
);
|
||||||
let inner = area.inner(Margin::new(1, 1));
|
let inner = area.inner(Margin::new(1, 1));
|
||||||
@@ -547,9 +589,16 @@ fn countdown_bar(remaining: u64, period: u64, width: usize) -> String {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pane_block(title: &'static str, focused: bool) -> Block<'static> {
|
fn pane_block<'a>(
|
||||||
|
title: impl Into<Line<'a>>,
|
||||||
|
focused: bool,
|
||||||
|
capability: ColorCapability,
|
||||||
|
) -> Block<'a> {
|
||||||
let style = if focused {
|
let style = if focused {
|
||||||
selected_style()
|
match capability {
|
||||||
|
ColorCapability::Color => Style::default().fg(ACCENT_COLOR),
|
||||||
|
ColorCapability::Monochrome => Style::default().add_modifier(Modifier::BOLD),
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
Style::default()
|
Style::default()
|
||||||
};
|
};
|
||||||
@@ -672,7 +721,7 @@ fn viewer_lines<'a>(
|
|||||||
Span::styled(
|
Span::styled(
|
||||||
format!("{label}: "),
|
format!("{label}: "),
|
||||||
Style::default()
|
Style::default()
|
||||||
.fg(Color::Cyan)
|
.fg(ACCENT_COLOR)
|
||||||
.add_modifier(Modifier::BOLD),
|
.add_modifier(Modifier::BOLD),
|
||||||
),
|
),
|
||||||
value,
|
value,
|
||||||
@@ -752,7 +801,7 @@ fn editor_lines(editor: &EntryEditor) -> Vec<Line<'_>> {
|
|||||||
let mut spans = vec![Span::styled(
|
let mut spans = vec![Span::styled(
|
||||||
format!("#{:02} {label}: ", index + 1),
|
format!("#{:02} {label}: ", index + 1),
|
||||||
Style::default()
|
Style::default()
|
||||||
.fg(Color::Cyan)
|
.fg(ACCENT_COLOR)
|
||||||
.add_modifier(Modifier::BOLD),
|
.add_modifier(Modifier::BOLD),
|
||||||
)];
|
)];
|
||||||
if let Ok(value) = std::str::from_utf8(contents) {
|
if let Ok(value) = std::str::from_utf8(contents) {
|
||||||
@@ -801,7 +850,7 @@ fn grep_lines(view: &crate::search::GrepView) -> Vec<Line<'_>> {
|
|||||||
} else {
|
} else {
|
||||||
Line::from(entry_line).style(
|
Line::from(entry_line).style(
|
||||||
Style::default()
|
Style::default()
|
||||||
.fg(Color::Cyan)
|
.fg(ACCENT_COLOR)
|
||||||
.add_modifier(Modifier::BOLD),
|
.add_modifier(Modifier::BOLD),
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
@@ -831,7 +880,7 @@ fn git_lines(view: &crate::app::GitView) -> Vec<Line<'_>> {
|
|||||||
Line::styled(
|
Line::styled(
|
||||||
view.message(),
|
view.message(),
|
||||||
Style::default()
|
Style::default()
|
||||||
.fg(Color::Cyan)
|
.fg(ACCENT_COLOR)
|
||||||
.add_modifier(Modifier::BOLD),
|
.add_modifier(Modifier::BOLD),
|
||||||
),
|
),
|
||||||
Line::raw(format!("repository: {}", snapshot.root().display())),
|
Line::raw(format!("repository: {}", snapshot.root().display())),
|
||||||
@@ -982,7 +1031,7 @@ fn prompt_line(app: &App) -> Paragraph<'static> {
|
|||||||
mod tests {
|
mod tests {
|
||||||
use std::ffi::OsStr;
|
use std::ffi::OsStr;
|
||||||
|
|
||||||
use ratatui::{Terminal, backend::TestBackend};
|
use ratatui::{Terminal, backend::TestBackend, buffer::Buffer};
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::app::Transition;
|
use crate::app::Transition;
|
||||||
@@ -1006,6 +1055,30 @@ mod tests {
|
|||||||
.join("\n")
|
.join("\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn render_buffer(width: u16, height: u16, app: &App, capability: ColorCapability) -> Buffer {
|
||||||
|
let backend = TestBackend::new(width, height);
|
||||||
|
let mut terminal = Terminal::new(backend).expect("test terminal");
|
||||||
|
terminal
|
||||||
|
.draw(|frame| draw_with_color_capability(frame, app, capability))
|
||||||
|
.expect("draw");
|
||||||
|
terminal.backend().buffer().clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn border_symbols(buffer: &Buffer, area: Rect) -> Vec<String> {
|
||||||
|
let right = area.right().saturating_sub(1);
|
||||||
|
let bottom = area.bottom().saturating_sub(1);
|
||||||
|
let mut symbols = Vec::new();
|
||||||
|
for x in area.left()..=right {
|
||||||
|
symbols.push(buffer[(x, area.top())].symbol().to_owned());
|
||||||
|
symbols.push(buffer[(x, bottom)].symbol().to_owned());
|
||||||
|
}
|
||||||
|
for y in area.top().saturating_add(1)..bottom {
|
||||||
|
symbols.push(buffer[(area.left(), y)].symbol().to_owned());
|
||||||
|
symbols.push(buffer[(right, y)].symbol().to_owned());
|
||||||
|
}
|
||||||
|
symbols
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn sizes_have_explicit_layout_classes() {
|
fn sizes_have_explicit_layout_classes() {
|
||||||
assert_eq!(layout_class(Rect::new(0, 0, 39, 20)), LayoutClass::TooSmall);
|
assert_eq!(layout_class(Rect::new(0, 0, 39, 20)), LayoutClass::TooSmall);
|
||||||
@@ -1066,6 +1139,46 @@ mod tests {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn pane_focus_changes_only_the_shared_accent_border_style() {
|
||||||
|
let mut app = App::new();
|
||||||
|
let sidebar = Rect::new(0, 0, 35, 17);
|
||||||
|
let main = Rect::new(35, 0, 65, 17);
|
||||||
|
let sidebar_focused = render_buffer(100, 20, &app, ColorCapability::Color);
|
||||||
|
assert_eq!(sidebar_focused[(0, 0)].fg, ACCENT_COLOR);
|
||||||
|
assert_eq!(sidebar_focused[(0, 0)].bg, Color::Reset);
|
||||||
|
assert!(!sidebar_focused[(0, 0)].modifier.contains(Modifier::BOLD));
|
||||||
|
assert_eq!(sidebar_focused[(35, 0)].fg, Color::Reset);
|
||||||
|
assert!(!sidebar_focused[(35, 0)].modifier.contains(Modifier::BOLD));
|
||||||
|
|
||||||
|
app.dispatch(crate::action::Action::FocusNext);
|
||||||
|
let main_focused = render_buffer(100, 20, &app, ColorCapability::Color);
|
||||||
|
assert_eq!(main_focused[(0, 0)].fg, Color::Reset);
|
||||||
|
assert!(!main_focused[(0, 0)].modifier.contains(Modifier::BOLD));
|
||||||
|
assert_eq!(main_focused[(35, 0)].fg, ACCENT_COLOR);
|
||||||
|
assert_eq!(main_focused[(35, 0)].bg, Color::Reset);
|
||||||
|
assert!(!main_focused[(35, 0)].modifier.contains(Modifier::BOLD));
|
||||||
|
assert_eq!(
|
||||||
|
border_symbols(&sidebar_focused, sidebar),
|
||||||
|
border_symbols(&main_focused, sidebar)
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
border_symbols(&sidebar_focused, main),
|
||||||
|
border_symbols(&main_focused, main)
|
||||||
|
);
|
||||||
|
|
||||||
|
let main_monochrome = render_buffer(100, 20, &app, ColorCapability::Monochrome);
|
||||||
|
assert_eq!(main_monochrome[(0, 0)].fg, Color::Reset);
|
||||||
|
assert_eq!(main_monochrome[(35, 0)].fg, Color::Reset);
|
||||||
|
assert!(!main_monochrome[(0, 0)].modifier.contains(Modifier::BOLD));
|
||||||
|
assert!(main_monochrome[(35, 0)].modifier.contains(Modifier::BOLD));
|
||||||
|
|
||||||
|
app.dispatch(crate::action::Action::Help);
|
||||||
|
let help = render_buffer(100, 20, &app, ColorCapability::Color);
|
||||||
|
assert_eq!(help[(0, 0)].fg, ACCENT_COLOR);
|
||||||
|
assert_eq!(help[(0, 0)].bg, Color::Reset);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn minimum_size_message_is_clear() {
|
fn minimum_size_message_is_clear() {
|
||||||
let output = render(39, 8, &App::new());
|
let output = render(39, 8, &App::new());
|
||||||
@@ -1647,7 +1760,7 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn selected_and_active_surfaces_use_one_high_contrast_style() {
|
fn selected_fields_status_and_results_keep_one_high_contrast_style() {
|
||||||
let mut app = App::new();
|
let mut app = App::new();
|
||||||
let document = fixture_document("otp/totp");
|
let document = fixture_document("otp/totp");
|
||||||
let otp_field = document
|
let otp_field = document
|
||||||
|
|||||||
Reference in New Issue
Block a user