Skip to content

Commit 5f59672

Browse files
committed
chore: Styling changes to align with Vite+.
1 parent e0d1add commit 5f59672

File tree

3 files changed

+76
-14
lines changed

3 files changed

+76
-14
lines changed

crates/vite_select/src/interactive.rs

Lines changed: 73 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,9 @@ use std::io::{Write, stdout};
33
use crossterm::{
44
cursor::{self, MoveToColumn},
55
event::{self, Event, KeyCode, KeyEvent, KeyEventKind, KeyModifiers},
6-
style::{Attribute, SetAttribute},
6+
style::{Attribute, Color, ResetColor, SetAttribute, SetForegroundColor},
77
terminal::{self, Clear, ClearType},
88
};
9-
use owo_colors::{OwoColorize, Stream};
109

1110
use crate::{RenderState, SelectItem, fuzzy::fuzzy_match};
1211

@@ -144,21 +143,21 @@ pub fn render_items(writer: &mut impl Write, params: &RenderParams<'_>) -> anyho
144143
lines += 1;
145144
}
146145

146+
let is_interactive = query.is_some();
147+
147148
// Prompt line (interactive only)
148149
if let Some(q) = query {
149-
let bold = SetAttribute(Attribute::Bold);
150-
let reset = SetAttribute(Attribute::Reset);
151150
// Print ": " separator before query only when query is non-empty,
152151
// to avoid a trailing space that Windows ConPTY would strip.
153152
if q.is_empty() {
154153
write!(
155154
writer,
156-
"{bold}Search task{reset} (\u{2191}/\u{2193} to move, enter to select):{line_ending}",
155+
"Select a task (\u{2191}/\u{2193}, Enter to run, Esc to clear):{line_ending}",
157156
)?;
158157
} else {
159158
write!(
160159
writer,
161-
"{bold}Search task{reset} (\u{2191}/\u{2193} to move, enter to select): {q}{line_ending}",
160+
"Select a task (\u{2191}/\u{2193}, Enter to run, Esc to clear): {q}{line_ending}",
162161
)?;
163162
}
164163
lines += 1;
@@ -171,8 +170,12 @@ pub fn render_items(writer: &mut impl Write, params: &RenderParams<'_>) -> anyho
171170
let is_selected = *selected_in_filtered == Some(vi);
172171

173172
// Truncate description to prevent line wrapping.
174-
// Line layout: prefix (2: "> " or " ") + label + ": " (2) + description
175-
let prefix_and_label_width = 2 + item.label.chars().count() + 2;
173+
// Line layout:
174+
// - interactive prefix is " › " or " " (4 chars)
175+
// - non-interactive prefix is " " (2 chars)
176+
// then label + ": " + description
177+
let prefix_width = if is_interactive { 4 } else { 2 };
178+
let prefix_and_label_width = prefix_width + item.label.chars().count() + 2;
176179
let max_desc_chars = params.max_line_width.saturating_sub(prefix_and_label_width);
177180
let desc_str = item.description.as_str();
178181
let desc_char_count = desc_str.chars().count();
@@ -186,18 +189,37 @@ pub fn render_items(writer: &mut impl Write, params: &RenderParams<'_>) -> anyho
186189
} else {
187190
desc_str
188191
};
189-
let desc = display_desc.if_supports_color(Stream::Stdout, |s| s.cyan());
190192

191-
if is_selected {
193+
if is_selected && is_interactive {
194+
write!(
195+
writer,
196+
"{blue}{bold} \u{203a} {label}: {desc}{reset}{line_ending}",
197+
blue = SetForegroundColor(Color::Blue),
198+
bold = SetAttribute(Attribute::Bold),
199+
label = item.label,
200+
desc = display_desc,
201+
reset = SetAttribute(Attribute::Reset),
202+
)?;
203+
} else if is_interactive {
204+
write!(
205+
writer,
206+
"{marker_color} {reset_color}{}:{command_color} {display_desc}{reset_color}{line_ending}",
207+
item.label,
208+
marker_color = SetForegroundColor(Color::DarkGrey),
209+
command_color = SetForegroundColor(Color::Grey),
210+
reset_color = ResetColor,
211+
)?;
212+
} else if is_selected {
192213
write!(
193214
writer,
194215
"{bold}> {label}: {desc}{reset}{line_ending}",
195216
bold = SetAttribute(Attribute::Bold),
196217
label = item.label,
218+
desc = display_desc,
197219
reset = SetAttribute(Attribute::Reset),
198220
)?;
199221
} else {
200-
write!(writer, " {}: {desc}{line_ending}", item.label)?;
222+
write!(writer, " {}: {display_desc}{line_ending}", item.label)?;
201223
}
202224
lines += 1;
203225
}
@@ -401,6 +423,33 @@ mod tests {
401423
strip_ansi(&String::from_utf8(buf).unwrap())
402424
}
403425

426+
#[expect(clippy::disallowed_types, reason = "test helper building arbitrary output string")]
427+
fn render_interactive_to_string(
428+
items: &[SelectItem],
429+
query: &str,
430+
max_line_width: usize,
431+
) -> String {
432+
let filtered: Vec<usize> = (0..items.len()).collect();
433+
let len = filtered.len();
434+
let mut buf = Vec::new();
435+
render_items(
436+
&mut buf,
437+
&RenderParams {
438+
items,
439+
filtered: &filtered,
440+
selected_in_filtered: Some(0),
441+
visible_range: 0..len,
442+
hidden_count: 0,
443+
header: None,
444+
query: Some(query),
445+
line_ending: "\n",
446+
max_line_width,
447+
},
448+
)
449+
.unwrap();
450+
strip_ansi(&String::from_utf8(buf).unwrap())
451+
}
452+
404453
#[test]
405454
fn truncates_long_description() {
406455
let items = make_items(&[("build", "a]really long command that exceeds the width limit")]);
@@ -463,4 +512,17 @@ mod tests {
463512
let line = output.lines().next().unwrap();
464513
assert!(line.contains("my-task"), "label should always be preserved: {line:?}");
465514
}
515+
516+
#[test]
517+
fn interactive_style_matches_vp_selector_marker_and_indent() {
518+
let items = make_items(&[("build", "echo build"), ("lint", "echo lint")]);
519+
let output = render_interactive_to_string(&items, "", 80);
520+
let mut lines = output.lines();
521+
let prompt = lines.next().unwrap();
522+
let selected = lines.next().unwrap();
523+
let unselected = lines.next().unwrap();
524+
assert_eq!(prompt, "Select a task (↑/↓, Enter to run, Esc to clear):");
525+
assert_eq!(selected, " › build: echo build");
526+
assert_eq!(unselected, " lint: echo lint");
527+
}
466528
}

crates/vite_task/src/session/reporter/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,7 @@ impl<T: owo_colors::OwoColorize> ColorizeExt for T {
194194
}
195195
}
196196

197-
const COMMAND_STYLE: Style = Style::new().cyan();
197+
const COMMAND_STYLE: Style = Style::new().blue();
198198
const CACHE_MISS_STYLE: Style = Style::new().purple();
199199

200200
/// Format the display's cwd as a string relative to the workspace root.

crates/vite_tui/src/config.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -402,7 +402,7 @@ fn project_directory() -> Option<ProjectDirs> {
402402
// Some(Color::Indexed(12))
403403
// } else if s == "bold magenta" {
404404
// Some(Color::Indexed(13))
405-
// } else if s == "bold cyan" {
405+
// } else if s == "bold blue" {
406406
// Some(Color::Indexed(14))
407407
// } else if s == "bold white" {
408408
// Some(Color::Indexed(15))
@@ -418,7 +418,7 @@ fn project_directory() -> Option<ProjectDirs> {
418418
// Some(Color::Indexed(4))
419419
// } else if s == "magenta" {
420420
// Some(Color::Indexed(5))
421-
// } else if s == "cyan" {
421+
// } else if s == "blue" {
422422
// Some(Color::Indexed(6))
423423
// } else if s == "white" {
424424
// Some(Color::Indexed(7))

0 commit comments

Comments
 (0)