Skip to content

Guide Quick Start

MeowLynxSea edited this page Jun 18, 2026 · 9 revisions

Quick start

Every Yororen UI app converges on this 6-step bootstrap.

1) Asset source

use gpui::Application;
use yororen_ui::assets::UiAsset;

let app = Application::new().with_assets(UiAsset);

UiAsset ships ~20 SVG icons under yororen_ui::headless::IconName. Compose multiple sources with CompositeAssetSource if you ship your own.

2) Renderer + theme

use gpui::App;
use yororen_ui::renderer;

fn init(cx: &mut App) {
    renderer::install(cx, cx.window_appearance());
}

renderer::install does three things in one call: picks system-light.json or system-dark.json by OS appearance, installs it as the global Theme, and registers the 55 default TokenXxxRenderer impls against the global RendererRegistry.

Swap the renderer with yororen_ui::brutalism_renderer::install(cx) (sharp corners, hard shadows) or pass a custom theme with yororen_ui_default_renderer::install_with(cx, my_theme). See Theming.

3) Text-input keymap

Required if your app uses any text input (text_input, password_input, search_input, number_input, file_path_input, text_area, keybinding_input, combo_box). Idempotent.

yororen_ui::headless::text_input::init(cx);

4) Locale

use yororen_ui::locale_en;
locale_en::install(cx);

Bundled: locale_en, locale_zh_cn, locale_ar. Layer app strings on top with yororen_ui::locale::install_with_translations. Arabic flips the layout to RTL via cx.i18n().text_direction().

5) Notification center (optional)

Only if you show toasts:

use yororen_ui::notification::NotificationCenter;
cx.set_global(NotificationCenter::new());

The center owns the queue and auto-dismiss timers. Your app still paints the host — see Notification.

6) Open the window

use gpui::{Bounds, WindowBounds, WindowOptions, px, size};

let options = WindowOptions {
    window_bounds: Some(WindowBounds::Windowed(
        Bounds::centered(None, size(px(800.), px(600.)), cx),
    )),
    ..Default::default()
};
cx.open_window(options, |_, cx| cx.new(|_cx| my_app::MyApp));

MyApp: Render is the root. Inside Render::render, cx.entity().clone() gives you the Entity<MyApp> to clone into 'static closures.

Whole main.rs

use gpui::{App, Application, Bounds, WindowBounds, WindowOptions, px, size};
use yororen_ui::assets::UiAsset;
use yororen_ui::locale_en;
use yororen_ui::renderer;

mod my_app;

fn main() {
    let app = Application::new().with_assets(UiAsset);

    app.run(|cx: &mut App| {
        renderer::install(cx, cx.window_appearance());
        yororen_ui::headless::text_input::init(cx);
        locale_en::install(cx);

        let options = WindowOptions {
            window_bounds: Some(WindowBounds::Windowed(
                Bounds::centered(None, size(px(800.), px(600.)), cx),
            )),
            ..Default::default()
        };
        cx.open_window(options, |_, cx| cx.new(|_cx| my_app::MyApp));
    });
}

App state

Yororen UI apps hold state in gpui::Entity<T>. Wrap it in a Global for cross-window access:

use gpui::{App, AppContext, Entity, Global};

#[derive(Default)]
pub struct Counter { pub value: i32 }

pub struct AppState { pub counter: Entity<Counter> }

impl AppState {
    pub fn new(cx: &mut App) -> Self {
        Self { counter: cx.new(|_| Counter::default()) }
    }
}
impl Global for AppState {}

cx.set_global(AppState::new(cx));

Read inside a render: cx.global::<AppState>().counter.read(cx).value. Update: state.update(cx, |s, cx| { s.value += 1; cx.notify(); }). cx.notify() is required to invalidate the window.

See also

Clone this wiki locally