slint-ui

Defines Slint UI conventions for building the gcl-ui desktop launcher interface in Rust.

Updated Sep 8, 2026
One-click install
npx skills add https://github.com/Sixdd6/grid-craft-launcher --skill slint-ui-sixdd6
Or copy as Structured Prompt for Agent▼
Please help me install this Agent Skill.
Skill: slint-ui
Source: https://github.com/Sixdd6/grid-craft-launcher/tree/main/.claude/skills/slint-ui
Command: npx skills add https://github.com/Sixdd6/grid-craft-launcher --skill slint-ui-sixdd6

SYSTEM DOCUMENTATION & REQUIREMENTS

What problem does it solve? Building the gcl-ui desktop interface requires consistent patterns across Slint layout files and Rust glue code; without shared conventions, screens leak logic, block the UI thread, deadlock on config locks, and break keyboard focus or dialog stacking. ## Core Features & Use Cases - Architecture rules: Enforces Theme-token styling, per-screen *State globals, pure layout screens, and the Bridge pattern that keeps every Launcher call off the UI thread. - Threading and lifecycle safety: Documents rules for ModelRc/Image UI-thread confinement, Weak<AppWindow> captures, generation counters for stale async results, and debounce timers for ComboBox/Slider controls. - Testing and preview workflow: Covers element id naming for the Slint testing backend, flow-test harness usage, Preview<Screen> components, and slint-viewer live reload. - Use Case: When adding a new settings control to the launcher, follow the skill to declare a Theme token, bind it through SettingsState, debounce its commit timer, name its element id, and verify it with a flow test. ## Quick Start Read this skill before editing any .slint file or gcl-ui Rust code, then follow its layout, Bridge, and state-global rules for your change.

Frequently Asked Questions about slint-ui

High-intent search queries and answers about installing and using this skill.

FAQPage Schema
How do I call Rust backend code from a Slint callback without blocking the UI?▼

Route the call through Bridge::run or Bridge::run_with_error, which spawns a plain thread for the Launcher call and posts the result back with upgrade_in_event_loop. Never invoke a Launcher method directly inside a callback body.

How do I share state between a Slint screen and Rust code?▼

Declare a per-screen global like InstancesState in ui/state.slint; the screen binds its layout to the global and Rust accesses it via window.global::<XState>(). Initialize every property empty and set all of them in the screen's open function.

Why does my Slint ComboBox save on every arrow key press?▼

A ComboBox reports every arrow step and wheel tick as selected, not just the settled value. Hold the pending value in a property and restart a named debounce Timer (about 500 ms) so the save fires once after the user stops.

Can I build Slint ModelRc or Image values on a worker thread?▼

No. ModelRc and slint::Image are UI-thread only and must be constructed inside the upgrade_in_event_loop closure or on the UI thread. Build raw data on the worker, then convert it after posting back.

How do I test Slint UI interactions in Rust flow tests?▼

Build the real AppWindow over a Launcher on a temp root, then address elements by their snake_case ids like "InstancesScreen::create_button" using click, type_into, and wait_until. Element names are only emitted in debug builds.

Why does a click after closing a Slint dialog land on an invisible overlay?▼

A dialog kept mounted retains a full-window TouchArea holding the pointer grab. Mount every dialog inside an `if <State>.xxx_open:` block so a closed dialog has no element in the tree, and gate touch areas on enabled: root.open.