kael_ui 0.2.0

Professional shadcn-inspired UI component library for Kael. 100+ accessible components for building beautiful, performant desktop applications.
use kael_ui::{components::scrollable::scrollable_vertical, prelude::*};
use std::path::PathBuf;

struct Assets {
    base: PathBuf,
}

impl kael::AssetSource for Assets {
    fn load(&self, path: &str) -> Result<Option<std::borrow::Cow<'static, [u8]>>> {
        std::fs::read(self.base.join(path))
            .map(|data| Some(std::borrow::Cow::Owned(data)))
            .map_err(|err| err.into())
    }

    fn list(&self, path: &str) -> Result<Vec<SharedString>> {
        std::fs::read_dir(self.base.join(path))
            .map(|entries| {
                entries
                    .filter_map(|entry| {
                        entry
                            .ok()
                            .and_then(|entry| entry.file_name().into_string().ok())
                            .map(SharedString::from)
                    })
                    .collect()
            })
            .map_err(|err| err.into())
    }
}

fn main() {
    Application::new()
        .with_assets(Assets {
            base: PathBuf::from(env!("CARGO_MANIFEST_DIR")),
        })
        .run(|cx| {
            kael_ui::init(cx);
            kael_ui::set_icon_base_path("assets/icons");
            install_theme(cx, Theme::dark());

            cx.open_window(
                WindowOptions {
                    titlebar: Some(TitlebarOptions {
                        title: Some("HTML Rendering Demo".into()),
                        ..Default::default()
                    }),
                    window_bounds: Some(WindowBounds::Windowed(Bounds {
                        origin: Point::default(),
                        size: size(px(900.0), px(900.0)),
                    })),
                    ..Default::default()
                },
                |_, cx| cx.new(|_| HtmlDemo),
            )
            .unwrap();
        });
}

struct HtmlDemo;

const DEMO_HTML: &str = r#"
<h1>HTML Rendering Demo</h1>
<p>This is a <strong>comprehensive</strong> demonstration of the <code>Html</code> component.</p>

<h2>Inline Formatting</h2>
<p>You can use <strong>bold</strong>, <em>italic</em>, <del>strikethrough</del>, and <code>inline code</code>.</p>

<h2>Links</h2>
<p>Visit <a href="https://example.com">Example</a> or check out <a href="https://www.rust-lang.org">Rust</a>.</p>

<h2>Code Blocks</h2>
<pre><code class="language-rust">fn main() {
    println!("Hello from kael_ui!");
    let x = 42;
}</code></pre>

<h2>Lists</h2>
<h3>Unordered</h3>
<ul>
    <li>First item</li>
    <li>Second item with <strong>bold</strong></li>
    <li>Third item with <code>code</code></li>
</ul>

<h3>Ordered</h3>
<ol>
    <li>Step one</li>
    <li>Step two</li>
    <li>Step three</li>
</ol>

<h2>Blockquote</h2>
<blockquote>
    <p>This is a blockquote with <strong>bold</strong> text.</p>
</blockquote>

<h2>Table</h2>
<table>
    <thead>
        <tr>
            <th>Feature</th>
            <th align="center">Status</th>
            <th align="right">Notes</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>Bold</td>
            <td align="center">Done</td>
            <td align="right">Works well</td>
        </tr>
        <tr>
            <td>Italic</td>
            <td align="center">Done</td>
            <td align="right">Perfect</td>
        </tr>
    </tbody>
</table>

<h2>Inline CSS Styles</h2>
<p>
    <span style="color: red">Red text</span>,
    <span style="color: #00aa00">Green hex</span>,
    <span style="color: rgb(0, 100, 255)">Blue RGB</span>,
    <span style="color: orange; font-weight: bold">Bold orange</span>,
    <span style="color: purple; font-style: italic">Italic purple</span>.
</p>
<p>
    <span style="background-color: yellow; color: black">Highlighted text</span> and
    <span style="background-color: #333; color: white">Dark background</span>.
</p>
<p>
    <span style="color: coral; font-weight: bold; font-style: italic">Bold italic coral</span> with
    <span style="color: teal">teal</span> and <span style="color: gold; font-weight: bold">gold</span> accents.
</p>

<h2>Images</h2>
<p>Images render natively via GPUI:</p>
<img src="assets/icons/zap.svg" alt="Zap icon">

<hr>
<p>Content below the horizontal rule.</p>
"#;

impl Render for HtmlDemo {
    fn render(&mut self, _window: &mut Window, _cx: &mut Context<Self>) -> impl IntoElement {
        let theme = use_theme();

        div()
            .size_full()
            .bg(theme.tokens.background)
            .overflow_hidden()
            .child(scrollable_vertical(
                div()
                    .flex()
                    .flex_col()
                    .p(px(32.0))
                    .max_w(px(800.0))
                    .child(Html::new(DEMO_HTML).base_font_size(px(15.0))),
            ))
    }
}