meowlynxsea/yororen-ui/yororen-ui-app-core
Claude Code and agent skill by meowlynxsea/yororen-ui
- community
Checking that the SKILL.md file is still in the repository.
App bootstrap and core architecture for end users building a gpui desktop app with Yororen UI (yororen_ui). Use when generating or refactoring main.rs, window setup, the one-call renderer install, the i18n bootstrap, NotificationCenter global, custom theme JSON, project module layout (state.rs, *app.rs, components/), Entity<T> state pattern, or theme reads via cx.theme(). Not for contributing to yororen-ui itself.
Install
npx vskill@latest install meowlynxsea/yororen-ui/yororen-ui-app-coreSKILL.md
Yororen UI App Core
Scaffold the foundation of a Yororen UI app: the one-call bootstrap, the three globals you'll set, the project layout the demos converge on, and the cross-cutting concerns (state, theme, i18n, notifications, animation, a11y, assets) that every app needs.
1. The one-call bootstrap
Every Yororen UI app starts the same way. main.rs is short on purpose:
That's the whole boot. Every other file in your app reads from these globals and renders. There is no app.run configuration beyond this.
A complete, with-everything-wired variant lives in `references/bootstrap-pattern.md`.
When to swap the renderer
The renderer::install call above uses the default renderer (the yororen-ui-default-renderer crate, with system-light.json / system-dark.json chosen by OS appearance). Three legitimate reasons to change it:
| If you want… | Use | |
|---|---|---|
| A custom theme, but the default look | default_renderer::install_with(cx, my_theme) | |
| A completely different visual (sharp corners, hard shadows) | yororen_ui::brutalism_renderer::install(cx) (feature-gated) | |
| A custom renderer for one component | cx.register_renderer_arc::<m::Button, dyn ButtonRenderer>(Arc::new(MyButtonRenderer)) |
See $yororen-ui-recipes for "Choosing a renderer".
2. Project layout
The five live demos (counter, layers_demo, inputs_demo, gallery_demo, theme_showcase) all converge on the same shape:
main.rs is only the bootstrap. state.rs is only the Entity<T>-wrapping-Global data model. *_app.rs is the root Render impl. Everything else (composite states, helper elements, panel layouts) lives in components/.
3. The state pattern
Yororen UI uses gpui's Entity<T> for all app state. The render layer tracks which entities a render closure read, so a single cx.notify() on the entity is enough to invalidate the window — no manual EntityId plumbing.
A render closure reads the state and chains mutations through update:
Two things to internalize:
- **Every
moveclosure that touches your state needs its ownEntity<T>
clone.** The closure owns the clone; the original entity handle stays in the global. A single state.counter.clone() per closure is cheap (it's an Arc bump).
- Mutate, then `cx.notify()`. gpui-ce 0.3 does not auto-notify
on entity update. The &mut Context inside update is what triggers re-render.
For a fuller version, see the `counter` demo in `crates/yororen-ui-demos/counter/`.
4. The Theme global and cx.theme()
The Theme is pub struct Theme(pub serde_json::Value). There is no Rust schema — the renderer reads paths like action.primary.bg and your code can do the same.
ActiveTheme is implemented for both App and Context<'_, T>, so cx.theme() works in any render closure without casting.
Authoring a custom theme
Write a JSON file, parse it, pass to install_with:
A minimal valid theme covers the top-level keys the renderers read: surface, content, border, action.{neutral,primary,danger}, status.{success,warning,danger,error,info,neutral}, tokens.control.<component>. Missing keys fall back to renderer defaults via get_color's Option<Hsla> return type.
For live theme switching at runtime (e.g. a "Next theme" toolbar button), call yororen_ui::theme::install(cx, new_theme) inside the render closure — every frame. The theme_showcase demo does this.
5. i18n
Three pieces:
- Framework strings ship as a
TranslationMapper locale in
yororen-ui-locale-{en,zh-CN,ar}. Install one with yororen_ui::locale::install_locale(cx, "en"|"zh-CN"|"ar") (or yororen_ui::locale_en::install(cx) for the short form).
- App strings are a
TranslationMapyou author (JSON via
include_str!, parsed by locale::parse_bundled_translations). Layer them on top with locale::install_with_translations(cx, "en", app_map).
- Lookups are
cx.t("key.path")everywhere; theTranslatetrait
is implemented for App. The full key is dot-separated; plural categories use tn("items", 5) which falls back to items.other if the count-specific form is missing.
The ar locale is RTL; cx.i18n().text_direction() returns TextDirection::Rtl for it. Components that read this direction via the rtl helpers will automatically flip padding / margin / icon positions. If your custom layout uses .left_* / .right_* directly instead of the start/end helpers, it will render wrong in RTL.
6. Notifications
If your app shows toasts, set the global and use it:
The NotificationCenter lives in yororen-ui-core/src/notification/ and is a thin state machine: it owns the queue, schedules auto-dismiss timers, and exposes items() for the renderer to paint. The renderer (visual) lives in yororen-ui-default-renderer's notification host; your app is responsible for wiring the host into the render tree (the gallery_demo shows the exact pattern, including the gpui::deferred(...).with_priority(3) wrap that puts toasts above modals).
Sticky semantics
Notification::sticky(true) upgrades dismiss to Manual automatically (both in the builder and in the scheduler, dual-guarded). Use it for notifications the user must explicitly dismiss — error alerts that need acknowledgment, etc. Default is non-sticky with a 4-second timer.
7. Animation primitives
The single concept you need: `AnimatedVisibility`. Every stateful composite (SelectState, ModalState, PopoverState, TooltipState, DropdownMenuState, ComboBoxState, MenuState) owns an animation: AnimatedVisibility field, and the renderer reads is_visible() / progress() / phase() to paint enter/exit transitions.
AnimatedVisibility itself is just target: bool, progress: f32 plus an update(dt) step. The orchestrator (in yororen-ui-core/src/animation/) drives the timer; the renderer reads the progress to scale / translate / fade. Default config is 200ms ease-out quadratic; presets (fade_in, scale_in, fade_slide_in_*, bounce_*, elastic_*) are in yororen-ui-core/src/animation/preset.rs.
8. a11y primitives
Four modules in yororen-ui-core/src/a11y/. They are opt-in per element — you don't get a global "a11y mode"; you compose what you need.
| Module | When to use | Pattern | |||
|---|---|---|---|---|---|
FocusTrap | modals that block navigation | `div().focus_trap().on_escape(\ | _,_,_\ | close()).child(content)` | |
ClickOutsideGuard | popovers / dropdowns / context menus | el.apply(div()).child(content) then guard close | |||
ScrollLockGuard | nested modals (prevent body scroll) | let _lock = ScrollLockGuard::acquire(); in the open path | |||
FocusableList / cycle_focus | keyboard nav between focusable items | list.push(id); ring.cycle(current_id, Next) |
9. The text-input keymap
If your app uses any text input (text_input, password_input, search_input, number_input, file_path_input, keybinding_input, text_area, or combo_box — anything that embeds a text input), call once at boot:
This is the start of the file. Read the full SKILL.md on GitHub.
Security
- Security scanPassed, 100 of 100Pattern checks on the skill's files.
- Model reviewNot runA model review is scheduled for the next rescan.
Quality evaluation
- Task evaluationNot runNo evaluation yet. Run one in Skill Studio.
Source
- SKILL.md in the repositoryCheckingcodex-skills/yororen-ui-app-core/SKILL.md
Popularity
- Repository stars
- 331
- Repository forks
- 9
- 7-day trend score
- 29
Stars and forks are for the whole GitHub repository, not this skill alone. Not refreshed yet.
Works with
Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.
- Claude Code
- Cursor
- GitHub Copilot
- Windsurf
- Codex
- Gemini CLI
- Cline
- Amp
- Roo Code
- Goose
- Continue
- Kilo Code
- Junie
- Trae
- OpenHands
- Qwen Code
- AI Agent
- Tabnine Chat
- Sourcegraph Cody
- Amazon Q
- Firebase Genkit
- Sweep
- Devin
- Phind
- Mentat
- Claude Desktop
- Aider
- GPT Pilot
- Plandex
- bolt.new
- v0
- Replit Agent
- Anse
- TypingMind
- BetterChatGPT
- LibreChat
- Warp AI
- Pieces
- Fig AI
Embed badge
[](https://verified-skill.com/skills/meowlynxsea/yororen-ui/yororen-ui-app-core)