use ratatui::style::{Color, Modifier, Style};
pub const PRIMARY: Color = Color::Rgb(99, 102, 241);
pub const PRIMARY_LIGHT: Color = Color::Rgb(129, 140, 248);
pub const PRIMARY_DARK: Color = Color::Rgb(79, 70, 229);
pub const SECONDARY: Color = Color::Rgb(20, 184, 166);
pub const ACCENT: Color = Color::Rgb(251, 191, 36);
pub const SUCCESS: Color = Color::Rgb(34, 197, 94);
pub const WARNING: Color = Color::Rgb(251, 146, 60);
pub const ERROR: Color = Color::Rgb(239, 68, 68);
pub const INFO: Color = Color::Rgb(56, 189, 248);
pub const BG_DARK: Color = Color::Rgb(15, 15, 25);
pub const BG_ELEVATED: Color = Color::Rgb(25, 25, 40);
pub const BG_SELECTION: Color = Color::Rgb(45, 45, 70);
pub const BG_HOVER: Color = Color::Rgb(55, 55, 85);
pub const BORDER: Color = Color::Rgb(100, 100, 120);
pub const BORDER_FOCUSED: Color = PRIMARY_LIGHT;
pub const BORDER_MUTED: Color = Color::Rgb(55, 55, 75);
pub const TEXT_PRIMARY: Color = Color::Rgb(245, 245, 250);
pub const TEXT_SECONDARY: Color = Color::Rgb(160, 160, 180);
pub const TEXT_MUTED: Color = Color::Rgb(100, 100, 120);
pub const TEXT_COMPLETED: Color = Color::Rgb(130, 130, 150);
pub const TEXT_DISABLED: Color = Color::Rgb(70, 70, 85);
pub const PROJECT: Color = Color::Rgb(96, 165, 250);
pub const TAG: Color = Color::Rgb(192, 132, 252);
pub const PRIORITY_URGENT: Color = ERROR;
pub const PRIORITY_HIGH: Color = WARNING;
pub const PRIORITY_NORMAL: Color = TEXT_SECONDARY;
pub const PRIORITY_LOW: Color = TEXT_MUTED;
pub const DUE_OVERDUE: Color = ERROR;
pub const DUE_TODAY: Color = ACCENT;
pub const DUE_WEEK: Color = INFO;
pub const DUE_LATER: Color = TEXT_MUTED;
pub const STATUS_PENDING: Color = ACCENT;
pub const STATUS_IN_PROGRESS: Color = PRIMARY_LIGHT;
pub const STATUS_COMPLETED: Color = SUCCESS;
pub const STATUS_ARCHIVED: Color = TEXT_MUTED;
pub mod icons {
pub const CHECKBOX_EMPTY: &str = "○";
pub const CHECKBOX_PROGRESS: &str = "◐";
pub const CHECKBOX_DONE: &str = "●";
pub const CHECKBOX_ARCHIVED: &str = "◌";
pub const PRIORITY_URGENT: &str = "▲";
pub const PRIORITY_HIGH: &str = "△";
pub const PRIORITY_LOW: &str = "▽";
pub const ARROW_RIGHT: &str = "→";
pub const ARROW_LEFT: &str = "←";
pub const CHEVRON_RIGHT: &str = "›";
pub const CHEVRON_DOWN: &str = "⌄";
pub const SELECTOR: &str = "▸";
pub const BULLET: &str = "•";
pub const PROJECT_PREFIX: &str = "@";
pub const TAG_PREFIX: &str = "#";
pub const CHECK: &str = "✓";
pub const CROSS: &str = "✗";
pub const WARNING_ICON: &str = "⚠";
pub const INFO_ICON: &str = "ℹ";
pub const SPARKLE: &str = "✦";
pub const STAR: &str = "★";
pub const DIAMOND: &str = "◆";
pub const CIRCLE: &str = "●";
pub const DOT: &str = "·";
pub const LINE_HORIZONTAL: &str = "─";
pub const LINE_VERTICAL: &str = "│";
pub const CORNER_TL: &str = "╭";
pub const CORNER_TR: &str = "╮";
pub const CORNER_BL: &str = "╰";
pub const CORNER_BR: &str = "╯";
pub const PROGRESS_EMPTY: &str = "░";
pub const PROGRESS_PARTIAL: &str = "▒";
pub const PROGRESS_FULL: &str = "█";
}
pub fn primary_style() -> Style {
Style::default().fg(PRIMARY_LIGHT)
}
pub fn heading_style() -> Style {
Style::default()
.fg(TEXT_PRIMARY)
.add_modifier(Modifier::BOLD)
}
pub fn subheading_style() -> Style {
Style::default().fg(TEXT_SECONDARY)
}
pub fn muted_style() -> Style {
Style::default().fg(TEXT_MUTED)
}
pub fn disabled_style() -> Style {
Style::default()
.fg(TEXT_DISABLED)
.add_modifier(Modifier::DIM)
}
pub fn border_focused_style() -> Style {
Style::default().fg(BORDER_FOCUSED)
}
pub fn border_style() -> Style {
Style::default().fg(BORDER)
}
pub fn selection_style() -> Style {
Style::default()
.bg(BG_SELECTION)
.add_modifier(Modifier::BOLD)
}
pub fn keybind_style() -> Style {
Style::default()
.fg(ACCENT)
.add_modifier(Modifier::BOLD)
}
pub fn success_style() -> Style {
Style::default().fg(SUCCESS)
}
pub fn warning_style() -> Style {
Style::default().fg(WARNING)
}
pub fn error_style() -> Style {
Style::default().fg(ERROR)
}
pub fn info_style() -> Style {
Style::default().fg(INFO)
}
pub fn gradient_bar(width: usize) -> String {
let chars = ['░', '▒', '▓', '█', '▓', '▒', '░'];
let segment_width = width / chars.len();
let mut result = String::new();
for (i, &ch) in chars.iter().enumerate() {
let count = if i == chars.len() / 2 {
width - (segment_width * (chars.len() - 1))
} else {
segment_width
};
for _ in 0..count {
result.push(ch);
}
}
result
}
pub fn progress_bar(progress: f32, width: usize) -> String {
let filled = (progress * width as f32) as usize;
let empty = width.saturating_sub(filled);
format!(
"{}{}",
icons::PROGRESS_FULL.repeat(filled),
icons::PROGRESS_EMPTY.repeat(empty)
)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_progress_bar() {
assert_eq!(progress_bar(0.5, 10), "█████░░░░░");
assert_eq!(progress_bar(1.0, 5), "█████");
assert_eq!(progress_bar(0.0, 5), "░░░░░");
}
#[test]
fn test_gradient_bar() {
let bar = gradient_bar(21);
assert_eq!(bar.chars().count(), 21);
}
}