kael_ui 0.2.0

Professional shadcn-inspired UI component library for Kael. 100+ accessible components for building beautiful, performant desktop applications.
use crate::animations::lerp_color;
use kael::{prelude::FluentBuilder as _, *};

#[derive(IntoElement)]
pub struct GradientText {
    text: SharedString,
    start_color: Option<Hsla>,
    end_color: Option<Hsla>,
    text_size: Option<Pixels>,
    font_weight: Option<FontWeight>,
    font_family: Option<SharedString>,
    style: StyleRefinement,
}

impl GradientText {
    pub fn new(text: impl Into<SharedString>) -> Self {
        Self {
            text: text.into(),
            start_color: None,
            end_color: None,
            text_size: None,
            font_weight: None,
            font_family: None,
            style: StyleRefinement::default(),
        }
    }

    pub fn start_color(mut self, color: Hsla) -> Self {
        self.start_color = Some(color);
        self
    }

    pub fn end_color(mut self, color: Hsla) -> Self {
        self.end_color = Some(color);
        self
    }

    pub fn text_size(mut self, size: Pixels) -> Self {
        self.text_size = Some(size);
        self
    }

    pub fn font_weight(mut self, weight: FontWeight) -> Self {
        self.font_weight = Some(weight);
        self
    }

    pub fn font_family(mut self, family: impl Into<SharedString>) -> Self {
        self.font_family = Some(family.into());
        self
    }
}

impl Styled for GradientText {
    fn style(&mut self) -> &mut StyleRefinement {
        &mut self.style
    }
}

impl RenderOnce for GradientText {
    fn render(self, _window: &mut Window, _cx: &mut App) -> impl IntoElement {
        let start = self.start_color.unwrap_or(hsla(0.6, 0.8, 0.6, 1.0));
        let end = self.end_color.unwrap_or(hsla(0.8, 0.8, 0.6, 1.0));

        let chars: Vec<char> = self.text.chars().collect();
        let count = chars.len();
        let max_index = if count > 1 { count - 1 } else { 1 };

        let text_size = self.text_size;
        let font_weight = self.font_weight;
        let font_family = self.font_family;
        let user_style = self.style;

        let mut row = div().flex().flex_row().items_center().map(|mut el| {
            el.style().refine(&user_style);
            el
        });

        for (i, ch) in chars.into_iter().enumerate() {
            let t = i as f32 / max_index as f32;
            let color = lerp_color(start, end, t);
            let s: SharedString = ch.to_string().into();

            let mut span = div().text_color(color).child(s);

            if let Some(size) = text_size {
                span = span.text_size(size);
            }
            if let Some(weight) = font_weight {
                span = span.font_weight(weight);
            }
            if let Some(ref family) = font_family {
                span = span.font_family(family.clone());
            }

            row = row.child(span);
        }

        row
    }
}