Theming and internationalization
This page is the reference contract for the app-wide presentation values that widgets read during component conversion.
Theming controls how the interface looks: color, typography, spacing, radius, elevation, motion, chart palettes, and component-level styling.
Internationalization, often shortened to i18n, controls how the interface supports multiple languages and locale-sensitive text selection.
Both systems flow through Env. Widgets read the current environment through ViewHandle, which means theme and locale are explicit inputs to rendering rather than hidden global state.
Theme types
| | |
|---|
| | Contains primitive tokens, component themes, and the resolved design-system metadata. |
| | Contains colors, spacing, typography, radius, elevation, motion, and data-visualization tokens. |
| Widget-ready component styles | Contains typed styles for buttons, inputs, badges, tabs, modals, cards, tooltips, progress bars, and related components. |
| Trait implemented by generated design systems | Produces metadata, token records, component specs, pattern specs, asset manifests, and light/dark themes. |
| | |
| Runtime copy of generated design-system metadata | Useful for diagnostics, tooling, docs, and theme inspection. |
The normal entry points are Theme::default() and Theme::dark(). Those use Fission's bundled default design system.
For a generated package, use the generated type:
use fission::theme::{DesignMode, DesignSystem, FissionDefaultDesignSystem};
let light = FissionDefaultDesignSystem::theme(DesignMode::Light);
let dark = FissionDefaultDesignSystem::theme(DesignMode::Dark);
Bundled design-system presets
Fission includes these build-time generated presets:
| | |
|---|
| FissionDefaultDesignSystem | crates/core/fission-theme/design/default |
| FissionMaterialDesign3DesignSystem | crates/core/fission-theme/design/material3 |
| FissionFluent2DesignSystem | crates/core/fission-theme/design/fluent2 |
| FissionLiquidGlassDesignSystem | crates/core/fission-theme/design/liquid-glass |
| FissionCupertinoDesignSystem | crates/core/fission-theme/design/cupertino |
Each preset is a normal Design System Package JSON input. The runtime does not parse those JSON files. The fission-theme build script runs the same design-system generator available to application projects and compiles the resulting Rust into the crate.
Use a preset when it matches the platform or brand direction you want. Copy it into your app and generate your own AppDesignSystem when the product needs different tokens.
Environment flow
Env carries the active theme, internationalization registry, locale, and other app-wide presentation context. During component conversion, widgets can read those values through view.env or convenience helpers such as view.theme().
Desktop exposes both with_env(...) and with_sync_env(...). Mobile and web expose with_sync_env(...). SSR apps expose with_env(...), i18n(...), translation_bundle(...), default_locale(...), locale_resolver(...), and with_request_env(...). Static site targets expose with_env(...).
Use with_env(...) to seed a base environment before the first frame, such as one that already contains translation bundles.
Use with_sync_env(...) when app state should update environment values every frame, such as mirroring a user-selected theme mode, locale, or window title into Env.
Use translation_bundle(...) or i18n(...) on FissionServerApp to register server-side bundles. Use default_locale(...) for the fallback locale and locale_resolver(...) when request data should select the locale before SSR, such as choosing from a path prefix, route parameter, header, cookie, or session. Use with_request_env(...) for other request-owned Env values. The server shell uses the resolved request Env for both widget building and lowering, so TextContent::Key resolves consistently in rendered HTML.
DesktopApp::new(MyApp)
.with_sync_env(|state: &MyState, env: &mut Env| {
env.theme = AppDesignSystem::theme(state.theme_mode);
env.locale = state.locale.clone();
})
.run()?;
Internationalization types
| | |
|---|
| Active language and region identifier | Examples include en-US and fr-FR. |
| Translated key-value messages for one locale | Usually loaded from app-owned files at startup. |
| Registry of translation bundles | Stored on Env so widgets can resolve keyed text. |
| Text content resolved through the active locale | Use for product copy that should be translated. |
| Text content rendered exactly as given | Use for already-translated strings, user data, file names, ids, or counts. |
The recommended translation file format for application code is YAML. Keep translation files in the repository, embed them with include_str!, parse them at startup into TranslationBundle values, add those bundles to env.i18n, and store the current locale choice in GlobalState.
The runtime contract is still TranslationBundle, not YAML itself. Advanced applications may generate bundles another way, but Fission documentation and examples use YAML plus include_str! as the default because it is deterministic, readable, and works consistently across every target.
Practical rules
Keep durable user choices such as locale preference, theme mode, and selected brand variant in GlobalState.
Keep loaded theme objects and translation bundles in Env because widgets need them as app-wide presentation context.
Avoid hard-coding unrelated color, spacing, and typography values inside widgets. If a value should be consistent across the product, it belongs in the design system or active theme.
Use TextContent::Key for product copy and TextContent::Literal for data. A label such as settings.title should be keyed. A user name, file path, generated count, or pasted message should usually be literal.
Related pages
For the step-by-step guide, read Theming and internationalization. For DSP generation and presets, read Design system. For the exact Env contract, see Environment, input, and input method editor.