Add quick-add mode for categories

N (from anywhere) or n (in Category panel) opens an inline prompt
to add categories one after another without typing :add-cat each time.

- Yellow border + prompt distinguishes it from item-add (green)
- Enter / Tab adds the category and clears the buffer, staying open
- Esc returns to the category list
- Cursor automatically moves to the newly added category

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Ed L
2026-03-21 23:03:45 -07:00
parent 4f322e53cd
commit c9d1313072
5 changed files with 311 additions and 19 deletions

View File

@ -24,12 +24,15 @@ impl<'a> CategoryPanel<'a> {
impl<'a> Widget for CategoryPanel<'a> {
fn render(self, area: Rect, buf: &mut Buffer) {
let is_item_add = matches!(self.mode, AppMode::ItemAdd { .. });
let is_active = matches!(self.mode, AppMode::CategoryPanel) || is_item_add;
let is_cat_add = matches!(self.mode, AppMode::CategoryAdd { .. });
let is_active = matches!(self.mode, AppMode::CategoryPanel) || is_item_add || is_cat_add;
let (border_color, title) = if is_item_add {
let (border_color, title) = if is_cat_add {
(Color::Yellow, " Categories — New category (Enter:add Esc:done) ")
} else if is_item_add {
(Color::Green, " Categories — Adding items (Enter:add Esc:done) ")
} else if is_active {
(Color::Cyan, " Categories a:add-items Space:cycle-axis ")
(Color::Cyan, " Categories n:new a:add-items Space:axis ")
} else {
(Color::DarkGray, " Categories ")
};
@ -108,19 +111,26 @@ impl<'a> Widget for CategoryPanel<'a> {
}
}
// Inline prompt at the bottom when in ItemAdd mode
if let AppMode::ItemAdd { category, buffer } = self.mode {
let sep_y = inner.y + list_height;
let prompt_y = sep_y + 1;
if sep_y < inner.y + inner.height {
let sep = "".repeat(inner.width as usize);
buf.set_string(inner.x, sep_y, &sep, Style::default().fg(Color::Green));
// Inline prompt at the bottom for CategoryAdd or ItemAdd
let (prompt_color, prompt_text) = match self.mode {
AppMode::CategoryAdd { buffer } => {
(Color::Yellow, format!(" + category: {buffer}"))
}
if prompt_y < inner.y + inner.height {
let prompt = format!(" + {buffer}");
buf.set_string(inner.x, prompt_y, &prompt,
Style::default().fg(Color::Green).add_modifier(Modifier::BOLD));
AppMode::ItemAdd { buffer, .. } => {
(Color::Green, format!(" + item: {buffer}"))
}
_ => return,
};
let sep_y = inner.y + list_height;
let prompt_y = sep_y + 1;
if sep_y < inner.y + inner.height {
let sep = "".repeat(inner.width as usize);
buf.set_string(inner.x, sep_y, &sep, Style::default().fg(prompt_color));
}
if prompt_y < inner.y + inner.height {
buf.set_string(inner.x, prompt_y, &prompt_text,
Style::default().fg(prompt_color).add_modifier(Modifier::BOLD));
}
}
}