# AGENTS.md — Theming repo guide for AI agents This is a Makepad 2.0 demo of runtime theme swapping. Read this before editing the codebase. ## What this repo is A small desktop app that shows how to push Rust-side state (theme + i18n) into a Makepad 2.0 `ScriptVm` and have the whole UI re-skin live. It is **not** a Makepad Studio plugin — it's a standalone Cargo binary that depends on `makepad-widgets` from git. ## Key files | File | Role | |---|---| | `src/main.rs` | `App` struct, `MatchEvent`, `AppMain`, and the `script_mod!` UI | | `src/theme.rs` | `ThemeState` enum, system detection, JSON persistence | | `src/i18n.rs` | `LanguageState` enum + `apply_to_vm` | | `src/streem_theme/mod.rs` | The four theme palettes + `s_themes` slot | | `src/streem_theme/{colors,shapes,typography}.rs` | Token vocabularies registered on the VM | | `src/streem_i18n/mod.rs` | EN + SW string tables + `s_i18n` slot | | `splash/theme_gallery.splash` | Standalone Splash script using the same palette | ## The runtime swap pattern The Rust side never touches widget properties directly. Instead: 1. `ThemeState::apply_to_vm(vm)` reassigns `mod.streem_theme.s_themes` via `script_eval!`. 2. `App::reload_ui_from_rust_state` re-runs `script_mod` and applies it with `Apply::Reload`, which re-evaluates every `draw_bg.color: color_bg` etc. in the tree. 3. `self.ui.redraw(cx)` triggers a repaint. The same pattern is used for `LanguageState` → `mod.streem_i18n.s_i18n`. ## Common edits ### Add a new theme 1. Add a variant to `ThemeState` in `src/theme.rs`. 2. Add a palette to `mod.streem_theme` in `src/streem_theme/mod.rs`. 3. Add a `themes.` alias in the same file. 4. Add a `Self::Variant => script_eval!(...)` arm in `ThemeState::apply_to_vm`. 5. Update `ThemeState::toggled()` to include the new variant in the cycle. 6. Update the tests in `src/theme.rs`. ### Add a new i18n key 1. Add the key to both `en` and `sw` blocks in `src/streem_i18n/mod.rs`. 2. Use it in the UI via `text: ` (with `use mod.streem_i18n.s_i18n.*` at the top of the `script_mod!` block). 3. If the key name collides with a widget `:=` name, rename the i18n key (prefix with `btn_`, `section_`, etc.). ### Change a theme color Edit the palette in `src/streem_theme/mod.rs`. If the same color appears in `splash/theme_gallery.splash`, update it there too. ## Gotchas - **`script_mod!` blocks in submodule files must be registered.** The v0.1 bug was that `colors.rs`, `shapes.rs`, and `typography.rs` declared `script_mod!` blocks but were never called from `AppMain::script_mod`. v0.2 fixes this by giving each a `pub fn script_mod(vm)` that runs `script_eval!`, called from the top-level `streem_theme::script_mod`. - **`System` must be resolved before `apply_to_vm`.** The Splash side never sees a `System` value — only the resolved `Light` or `Dark` palette. - **`new_batch: true`** is required on any View with `show_bg: true` that contains text children. Without it, text renders behind the background. - **Default text color is white.** For light themes, set `draw_text.color` to a dark color on every text widget. - **Hex colors containing `e`** adjacent to digits need the `#x` prefix inside `script_mod!` to avoid parse errors. E.g. `#x1E293B` not `#1E293B`. ## Running ```sh just run # or: cargo run just test # runs the ThemeState and LanguageState unit tests just ci # fmt-check + clippy + test (what CI runs) ``` The Makepad git dependency requires a recent Rust toolchain and, on Linux, the usual X11/ALSA/pkg-config dev packages (see README). ## Splash reference For the full Makepad 2.0 Splash scripting manual, see the `splash.md` file in the Makepad monorepo at `tools/splash.md` or the Makepad docs. The key rules: `height: Fit` on every container, `width: Fill` on the root, `:=` for named children, no commas between properties.