0.x

Teksilo is pre-1.0: breaking changes land between minor versions, so pin the version you tested against. How to pin it →

Get started

Install the crate, write the smallest application that runs, and get the toolchain, the system packages, the feature flags and the examples you need to go further.

cargo new my-app
cd my-app
cargo add teksilo

That is the whole install. Teksilo is at version 0.8.0 and every crate in the workspace shares that number, so there is one version to pin and one set of release notes to read. Pre-1.0 means breaking changes between minor versions: pin the exact version you tested against rather than a caret range, and read the news page before you move.

A minimal app

use teksilo::prelude::*;
use teksilo::widgets::Button;

fn main() {
    TeksiloAppBuilder::new()
        .theme(intui::light())
        .initial_window(
            WindowConfig::new()
                .title("Hello Teksilo")
                .size(400, 300)
                .root(|tree, _state| {
                    tree.add(
                        Button::new(lit!("Click Me"))
                            .on_activate_fn(|_ctx| println!("Clicked!")),
                    )
                }),
        )
        .run();
}

Three things in that snippet trip people up:

Reactive state is one type, Signal<T>, and derived values are ordinary maps over it:

use teksilo::prelude::*;
use teksilo::widgets::{Button, TextWidget, VStack};

fn main() {
    TeksiloAppBuilder::new()
        .theme(intui::light())
        .initial_window(
            WindowConfig::new()
                .title("Counter")
                .size(300, 150)
                .root(|tree, _state| {
                    let count = Signal::new(0_i32);
                    let label = count.map(|n| format!("Count: {n}"));
                    tree.add(
                        VStack::new()
                            .spacing(12.0)
                            .child(TextWidget::new(lit!("")).text(label))
                            .child(
                                Button::new(lit!("Increment"))
                                    .on_activate_fn(move |_| {
                                        count.set(count.get() + 1)
                                    }),
                            ),
                    )
                }),
        )
        .run();
}

Both snippets come from the README, and both compile as written against the 0.8.0 API.

Toolchain and system packages

What you get by default

The default feature set of the teksilo crate is widgets, text, i18n, inspector, toast, file-dialog, clipboard, fonts-arabic and fonts-hebrew. That gives you the widget catalog, the rich-text stack, compile-time-checked translations, the F12 debug inspector (debug builds only), toast notifications, native file dialogs and the system clipboard.

Off by default, added when you need them:

Read the examples

The runnable examples live in the repository, one package each, and most are invoked by a hyphenated package name:

cargo run -p simple-button      # the minimal app
cargo run -p widget-catalog     # browse most of the catalog
cargo run -p data-collections   # lists and trees over the data models
cargo run -p docking            # a dockable editor shell
cargo run -p file-dialogs       # native open, save and pick-folder

widget-catalog takes a --theme flag to start in a specific preset, one of intui-light, intui-dark, material3-light, material3-dark, fluent-light, fluent-dark, macos-light or macos-dark. simple-button is the closest thing in the repository to the first snippet above, with the inspector and the automation bridge added.

cargo run -p teksilo-widgets-previewer opens a three-pane explorer with live property editing, covering 56 of the widgets.

Before you build something on it

Where to go next