windjammer-ui 0.3.6

Cross-platform UI framework for Windjammer (Web, Desktop, Mobile)
Documentation
// Timeline Component - Chronological event display

use super::traits::Renderable

pub struct TimelineEvent {
    title: string,
    description: string,
    timestamp: string,
    icon: string,
    color: string,
}

impl TimelineEvent {
    pub fn new(title: string, timestamp: string) -> TimelineEvent {
        TimelineEvent {
            title: title,
            description: String::new(),
            timestamp: timestamp,
            icon: "●".to_string(),
            color: "#3b82f6".to_string(),
        }
    }

    pub fn description(self, desc: string) -> TimelineEvent {
        self.description = desc;
        self
    }

    pub fn icon(self, icon: string) -> TimelineEvent {
        self.icon = icon;
        self
    }

    pub fn color(self, color: string) -> TimelineEvent {
        self.color = color;
        self
    }
}

pub struct Timeline {
    events: Vec<TimelineEvent>,
}

impl Timeline {
    pub fn new() -> Timeline {
        Timeline {
            events: Vec::new(),
        }
    }

    pub fn event(self, event: TimelineEvent) -> Timeline {
        self.events.push(event);
        self
    }

}

impl Renderable for Timeline {
fn render(self) -> string {
        let mut html = String::new();

        html.push_str("<div style='position: relative; padding-left: 32px;'>");

        // Vertical line
        html.push_str("<div style='position: absolute; left: 8px; top: 0; bottom: 0; width: 2px; background: #e2e8f0;'></div>");

        for (_event_index, event) in self.events.iter().enumerate() {
            html.push_str("<div style='position: relative; padding-bottom: 32px;'>");

            // Icon/dot
            html.push_str("<div style='position: absolute; left: -24px; width: 16px; height: 16px; border-radius: 50%; background: ");
            html.push_str(&event.color);
            html.push_str("; border: 2px solid white; display: flex; align-items: center; justify-content: center; color: white; font-size: 10px;'>");
            html.push_str(&event.icon);
            html.push_str("</div>");

            // Content
            html.push_str("<div style='background: white; border: 1px solid #e2e8f0; border-radius: 8px; padding: 16px; box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);'>");

            // Timestamp
            html.push_str("<div style='font-size: 12px; color: #718096; margin-bottom: 4px;'>");
            html.push_str(&event.timestamp);
            html.push_str("</div>");

            // Title
            html.push_str("<div style='font-weight: 600; font-size: 16px; color: #1a202c; margin-bottom: 8px;'>");
            html.push_str(&event.title);
            html.push_str("</div>");

            // Description
            if event.description.len() > 0 {
                html.push_str("<div style='font-size: 14px; color: #4a5568;'>");
                html.push_str(&event.description);
                html.push_str("</div>");
            }

            html.push_str("</div>");

            html.push_str("</div>");
        }

        html.push_str("</div>");
        html
    }
}