dioxus-theme-core 0.1.0-alpha.5

Serializable custom theme configuration for no-reload Dioxus theme switching.
Documentation

dioxus-theme-core

Serializable custom theme configuration for no-reload Dioxus theme switching.

This crate is part of the Dioxus SSR package workspace. The APIs are pre-1.0 and may change between releases while the package family stabilizes.

Release Status

  • Current crate version: 0.1.0-alpha.4.
  • Release wave: June 8, 2026 workspace integration update.
  • Publish status: Prepared as a crates.io update for this package.
  • Scope: Serializable custom theme configuration for no-reload Dioxus theme switching.
  • The README install examples and local workspace dependency requirements are aligned with this publish wave.

API Syntax Gallery

Generated from the crate's rustdoc JSON so the visible syntax tracks the public API surface used for DX review.

Checked Import Smoke Test

extern crate dioxus_theme_core as api;

fn main() {
    let _ = core::any::type_name::<api::ThemeVisualTokenRole>();
}

crate root

Modules

pub mod prelude;

Re-exports

pub use integration::*;

Constants

pub const DEFAULT_THEME_RUNTIME_BASE_PATH: &str;
pub const DEFAULT_THEME_RUNTIME_VERSION: &str;
pub const DEFAULT_THEME_RUNTIME_PATH: &str;
pub const THEME_PACKAGE_NAME: &str;
pub const THEME_PACKAGE_VERSION: &str;
pub const DEFAULT_THEME_STORAGE_KEY: &str;
pub const DEFAULT_THEME_ATTRIBUTE: &str;
pub const DEFAULT_THEME_TARGET: &str;
pub const DEFAULT_THEME_DURATION_MS: u32;
pub const DEFAULT_THEME_EASING: &str;
pub const DEFAULT_THEME_ANIMATION_STORAGE_KEY: &str;
pub const DEFAULT_THEME_ANIMATION_SPEED: u16;
pub const DEFAULT_THEME_ANIMATION_SPEED_STORAGE_KEY: &str;
pub const MIN_THEME_ANIMATION_SPEED: u16;
pub const MAX_THEME_ANIMATION_SPEED: u16;
pub const THEME_TOKEN_BG: &str;
pub const THEME_TOKEN_FG: &str;
pub const THEME_TOKEN_MUTED: &str;
pub const THEME_TOKEN_PANEL: &str;
pub const THEME_TOKEN_PANEL_BORDER: &str;
pub const THEME_TOKEN_ACCENT: &str;
pub const THEME_TOKEN_BACKGROUND: &str;
pub const THEME_TOKEN_TEXT: &str;
pub const THEME_TOKEN_SURFACE: &str;
pub const THEME_TOKEN_SURFACE_BORDER: &str;
pub const THEME_CHANGE_EVENT: &str;
pub const THEME_VISUAL_TOKEN_MANIFEST_VERSION: u8;
pub const THEME_VISUAL_TOKENS: [ThemeVisualTokenDefinition; 6];

Type Aliases

pub type ThemeCfg = ThemeConfig;
pub type ThemeDef = ThemeDefinition;
pub type ThemeReg = ThemeRegistry;
pub type ThemeAnim = ThemeAnimationMode;
pub type ThemePreset = ThemeAnimationPreset;

Free Functions

theme_visual_token_css_var(alias: impl AsRef<str>) -> Option<&'static str>
const theme_visual_token_manifest() -> ThemeVisualTokenManifest
theme_visual_token_manifest_json() -> Result<String, serde_json::Error>
theme() -> ThemeConfig
theme_def(id: impl AsRef<str>, label: impl Into<String>) -> ThemeDefinition
themes() -> ThemeRegistry
default_themes() -> ThemeRegistry
motion() -> ThemeMotion
apply_theme_manifest_hook<H>(config: &ThemeConfig, policy: &ThemeRoutePolicy, hook: &H) -> Option<ThemeManifestFragment>
theme_route_policy() -> ThemeRoutePolicy
theme_output_budget() -> ThemeOutputBudget
theme_cache_key(config: &ThemeConfig, route: Option<&str>, extra: Option<&str>) -> String
theme_manifest_fragment(config: &ThemeConfig, policy: &ThemeRoutePolicy) -> ThemeManifestFragment
theme_output_report(config: &ThemeConfig, policy: &ThemeRoutePolicy) -> ThemeOutputReport
explain_theme(config: &ThemeConfig, policy: &ThemeRoutePolicy) -> ThemeExplainReport
theme_compatibility_matrix() -> ThemeCompatibilityMatrix
theme_native_port_hints(config: &ThemeConfig, policy: &ThemeRoutePolicy) -> std::collections::BTreeMap<String, String>
theme_id(id: impl AsRef<str>) -> String
is_custom_property_name(name: &str) -> bool
is_valid_theme_target(target: &str) -> bool
is_valid_theme_attribute(attribute: &str) -> bool
normalize_animation_speed(speed: u16) -> u16
theme_tokens_css(theme: &ThemeDefinition) -> String
is_safe_css_token_value(value: &str) -> bool

Types, Variants, Fields, and Methods

pub enum ThemeVisualTokenRole { ... }
variants: Background, Text, Muted, Surface, SurfaceBorder, Accent
methods:
  value.as_attr() -> &'static str
  value.js_key() -> &'static str
  value.css_var() -> &'static str
pub struct ThemeVisualTokenDefinition { ... }
fields:
  .role: ThemeVisualTokenRole
  .key: &'static str
  .css_var: &'static str
pub struct ThemeVisualTokenManifest { ... }
fields:
  .version: u8
  .change_event: &'static str
  .tokens: &'static [ThemeVisualTokenDefinition]
pub enum ThemeColorScheme { ... }
variants: Light, Dark, System, Normal
methods:
  value.as_css() -> &'static str
pub enum ThemeAnimationMode { ... }
variants: ViewTransition, CssOnly, None
methods:
  value.as_attr() -> &'static str
  value.is_animated() -> bool
pub enum ThemeAnimationPreset { ... }
variants: Fade, CrossFade, Slide, RadialWipe, MaskedWave
methods:
  ThemeAnimationPreset::all() -> &'static [Self; 5]
  value.as_attr() -> &'static str
  value.label() -> &'static str
pub enum ThemeReducedMotion { ... }
variants: Respect, Ignore
methods:
  value.as_attr() -> &'static str
pub enum ThemeValidationSeverity { ... }
variants: Error, Warning
pub enum ThemeValidationCode { ... }
variants: EmptyStorageKey, EmptyAnimationStorageKey, EmptyAnimationSpeedStorageKey, MissingDefaultTheme, MissingSystemLightTheme, MissingSystemDarkTheme, InvalidTarget, InvalidAttribute, InvalidTokenName, UnsafeTokenValue
pub struct ThemeValidationIssue { ... }
fields:
  .severity: ThemeValidationSeverity
  .code: ThemeValidationCode
  .message: String
  .field: Option<String>
  .theme: Option<String>
methods:
  ThemeValidationIssue::error(code: ThemeValidationCode, field: impl Into<String>, message: impl Into<String>) -> Self
  ThemeValidationIssue::token_error(code: ThemeValidationCode, theme: impl Into<String>, field: impl Into<String>, message: impl Into<String>) -> Self
pub struct ThemeValidationReport { ... }
fields:
  .issues: Vec<ThemeValidationIssue>
methods:
  value.is_valid() -> bool
  value.errors() -> impl Iterator<Item = &ThemeValidationIssue>
  value.warnings() -> impl Iterator<Item = &ThemeValidationIssue>
  value.push(issue: ThemeValidationIssue)
pub struct ThemeDefinition { ... }
fields:
  .id: String
  .label: String
  .color_scheme: ThemeColorScheme
  .tokens: std::collections::BTreeMap<String, String>
methods:
  ThemeDefinition::new(id: impl AsRef<str>, label: impl Into<String>) -> Self
  ThemeDefinition::light() -> Self
  ThemeDefinition::dark() -> Self
  ThemeDefinition::system() -> Self
  value.with_label(label: impl Into<String>) -> Self
  value.label(label: impl Into<String>) -> Self
  value.with_color_scheme(color_scheme: ThemeColorScheme) -> Self
  value.scheme(color_scheme: ThemeColorScheme) -> Self
  value.with_token(name: impl Into<String>, value: impl Into<String>) -> Self
  value.token(name: impl Into<String>, value: impl Into<String>) -> Self
  value.with_visual_token(role: ThemeVisualTokenRole, value: impl Into<String>) -> Self
  value.visual(role: ThemeVisualTokenRole, value: impl Into<String>) -> Self
  value.with_visual_tokens<I, V>(tokens: I) -> Self
  value.visuals<I, V>(tokens: I) -> Self
  value.with_tokens<I, K, V>(tokens: I) -> Self
  value.tokens<I, K, V>(tokens: I) -> Self
  value.is_system() -> bool
pub struct ThemeRegistry { ... }
fields:
  .themes: Vec<ThemeDefinition>
methods:
  ThemeRegistry::new() -> Self
  ThemeRegistry::defaults() -> Self
  value.with_theme(theme: ThemeDefinition) -> Self
  value.add(theme: ThemeDefinition) -> Self
  value.insert_theme(theme: ThemeDefinition) -> Option<ThemeDefinition>
  value.contains_theme(id: impl AsRef<str>) -> bool
  value.theme(id: impl AsRef<str>) -> Option<&ThemeDefinition>
  value.theme_ids() -> Vec<&str>
  value.ids() -> Vec<&str>
  value.first_non_system_theme() -> Option<&ThemeDefinition>
pub struct ThemeMotion { ... }
fields:
  .duration_ms: Option<u32>
  .easing: Option<String>
  .reduced_motion: Option<ThemeReducedMotion>
  .animation: Option<ThemeAnimationMode>
  .preset: Option<ThemeAnimationPreset>
  .speed: Option<u16>
methods:
  ThemeMotion::new() -> Self
  value.dur(duration: Duration) -> Self
  value.dur_ms(duration_ms: u32) -> Self
  value.ease(easing: impl Into<String>) -> Self
  value.reduced(reduced_motion: ThemeReducedMotion) -> Self
  value.anim(animation: ThemeAnimationMode) -> Self
  value.preset(preset: ThemeAnimationPreset) -> Self
  value.speed(speed: u16) -> Self
pub struct ThemeConfig { ... }
fields:
  .registry: ThemeRegistry
  .default_theme: String
  .system_light_theme: String
  .system_dark_theme: String
  .storage_key: String
  .attribute: String
  .target: String
  .duration_ms: u32
  .easing: String
  .reduced_motion: ThemeReducedMotion
  .animation: ThemeAnimationMode
  .animation_preset: ThemeAnimationPreset
  .animation_storage_key: String
  .animation_speed: u16
  .animation_speed_storage_key: String
  .isolate_view_transition_names: bool
  .runtime_path: String
methods:
  ThemeConfig::new() -> Self
  value.with_registry(registry: ThemeRegistry) -> Self
  value.registry(registry: ThemeRegistry) -> Self
  value.with_theme(theme: ThemeDefinition) -> Self
  value.theme(theme: ThemeDefinition) -> Self
  value.add(theme: ThemeDefinition) -> Self
  value.with_default_theme(theme: impl AsRef<str>) -> Self
  value.default_theme(theme: impl AsRef<str>) -> Self
  value.with_system_theme(light_theme: impl AsRef<str>, dark_theme: impl AsRef<str>) -> Self
  value.system_theme(light_theme: impl AsRef<str>, dark_theme: impl AsRef<str>) -> Self
  value.with_storage_key(storage_key: impl Into<String>) -> Self
  value.storage(storage_key: impl Into<String>) -> Self
  value.with_attribute(attribute: impl Into<String>) -> Self
  value.attr(attribute: impl Into<String>) -> Self
  value.with_target(target: impl Into<String>) -> Self
  value.target(target: impl Into<String>) -> Self
  value.with_duration_ms(duration_ms: u32) -> Self
  value.dur(duration: Duration) -> Self
  value.dur_ms(duration_ms: u32) -> Self
  value.with_easing(easing: impl Into<String>) -> Self
  value.ease(easing: impl Into<String>) -> Self
  value.with_reduced_motion(reduced_motion: ThemeReducedMotion) -> Self
  value.reduced(reduced_motion: ThemeReducedMotion) -> Self
  value.with_animation(animation: ThemeAnimationMode) -> Self
  value.anim(animation: ThemeAnimationMode) -> Self
  value.with_animation_preset(animation_preset: ThemeAnimationPreset) -> Self
  value.preset(animation_preset: ThemeAnimationPreset) -> Self
  value.with_animation_storage_key(animation_storage_key: impl Into<String>) -> Self
  value.anim_storage(animation_storage_key: impl Into<String>) -> Self
  value.with_animation_speed(animation_speed: u16) -> Self
  value.speed(animation_speed: u16) -> Self
  value.with_animation_speed_storage_key(animation_speed_storage_key: impl Into<String>) -> Self
  value.speed_storage(animation_speed_storage_key: impl Into<String>) -> Self
  value.with_view_transition_name_isolation(isolate: bool) -> Self
  value.isolate_names(isolate: bool) -> Self
  value.with_runtime_path(runtime_path: impl Into<String>) -> Self
  value.runtime(runtime_path: impl Into<String>) -> Self
  value.motion(motion: ThemeMotion) -> Self
  value.validate() -> ThemeValidationReport
  value.resolve_theme(id: impl AsRef<str>) -> Option<&ThemeDefinition>
  value.toggle_theme_id(current: impl AsRef<str>) -> String
  value.to_json() -> Result<String, serde_json::Error>
  value.to_compact_json() -> Result<String, serde_json::Error>
  value.to_preferred_json(format: ThemeSerializationFormat) -> Result<String, serde_json::Error>
  value.with_route_profile(profile: ThemePresetProfile) -> Self
  value.route_profile(profile: ThemePresetProfile) -> Self
  value.cache_key(route: Option<&str>) -> String
  value.manifest_fragment(policy: &ThemeRoutePolicy) -> ThemeManifestFragment
  value.output_report(policy: &ThemeRoutePolicy) -> ThemeOutputReport
  value.explain(policy: &ThemeRoutePolicy) -> ThemeExplainReport
  value.try_validated() -> Result<Self, ThemeConfigError>
pub struct ThemeConfigError { ... }
fields:
  .report: ThemeValidationReport
pub enum ThemeRuntimeEmission { ... }
variants: Always, WhenUsed, PrepaintOnly, Disabled
methods:
  value.as_attr() -> &'static str
pub enum ThemeSerializationFormat { ... }
variants: StableJson, ReadableJson, CompactJson
methods:
  value.as_attr() -> &'static str
pub enum ThemeDiagnosticVerbosity { ... }
variants: Off, Summary, Detailed
pub enum ThemeFallbackStrategy { ... }
variants: SystemTheme, StaticTokens, NativePort, DisableRuntime
pub enum ThemePresetProfile { ... }
variants: Conservative, Balanced, Expressive
methods:
  value.as_attr() -> &'static str
  value.apply_to_config(config: &mut ThemeConfig)
pub struct ThemeInteropPolicy { ... }
fields:
  .strata: bool
  .resume: bool
  .native_port: bool
  .viewtx: bool
  .hoverfx: bool
  .textfx: bool
pub struct ThemeOutputBudget { ... }
fields:
  .max_config_bytes: Option<usize>
  .max_runtime_bytes: Option<usize>
  .max_style_bytes: Option<usize>
  .max_theme_count: Option<usize>
methods:
  ThemeOutputBudget::new() -> Self
  value.config_bytes(max: usize) -> Self
  value.runtime_bytes(max: usize) -> Self
  value.style_bytes(max: usize) -> Self
  value.theme_count(max: usize) -> Self
pub struct ThemeRoutePolicy { ... }
fields:
  .route: Option<String>
  .enabled: bool
  .profile: ThemePresetProfile
  .emission: ThemeRuntimeEmission
  .serialization: ThemeSerializationFormat
  .diagnostics: ThemeDiagnosticVerbosity
  .fallback: ThemeFallbackStrategy
  .interop: ThemeInteropPolicy
  .budget: ThemeOutputBudget
  .labels: std::collections::BTreeMap<String, String>
  .tags: Vec<String>
methods:
  ThemeRoutePolicy::new() -> Self
  value.route(route: impl Into<String>) -> Self
  value.enabled(enabled: bool) -> Self
  value.profile(profile: ThemePresetProfile) -> Self
  value.emission(emission: ThemeRuntimeEmission) -> Self
  value.serialization(serialization: ThemeSerializationFormat) -> Self
  value.diagnostics(diagnostics: ThemeDiagnosticVerbosity) -> Self
  value.fallback(fallback: ThemeFallbackStrategy) -> Self
  value.budget(budget: ThemeOutputBudget) -> Self
  value.label(key: impl Into<String>, value: impl Into<String>) -> Self
  value.tag(tag: impl Into<String>) -> Self
pub struct ThemeManifestFragment { ... }
fields:
  .package: String
  .version: String
  .route: Option<String>
  .enabled: bool
  .cache_key: String
  .default_theme: String
  .runtime_path: String
  .profile: ThemePresetProfile
  .emission: ThemeRuntimeEmission
  .fallback: ThemeFallbackStrategy
  .labels: std::collections::BTreeMap<String, String>
  .tags: Vec<String>
  .metrics: std::collections::BTreeMap<String, u64>
  .policies: std::collections::BTreeMap<String, serde_json::Value>
pub struct ThemeOutputViolation { ... }
fields:
  .field: String
  .actual: usize
  .budget: usize
pub struct ThemeOutputReport { ... }
fields:
  .package: String
  .route: Option<String>
  .cache_key: String
  .config_bytes: usize
  .runtime_bytes: usize
  .style_bytes: usize
  .theme_count: usize
  .violations: Vec<ThemeOutputViolation>
methods:
  value.is_within_budget() -> bool
pub struct ThemeExplainReport { ... }
fields:
  .package: String
  .route: Option<String>
  .cache_key: String
  .runtime_decision: String
  .token_decision: String
  .fallback_decision: String
  .validation: ThemeValidationReport
  .manifest: ThemeManifestFragment
  .output: ThemeOutputReport
  .notes: Vec<String>
pub struct ThemeCompatibilityRow { ... }
fields:
  .target: String
  .support: String
  .runtime: String
  .fallback: String
  .notes: String
pub struct ThemeCompatibilityMatrix { ... }
fields:
  .package: String
  .rows: Vec<ThemeCompatibilityRow>
pub trait ThemeManifestPolicyHook { ... }
  fn apply(self: &Self, fragment: ThemeManifestFragment) -> Option<ThemeManifestFragment>;

prelude

Re-exports

pub use crate::ThemeAnim as ThemeAnim;
pub use crate::ThemeAnimationMode as ThemeAnimationMode;
pub use crate::ThemeCfg as ThemeCfg;
pub use crate::ThemeColorScheme as ThemeColorScheme;
pub use crate::ThemeCompatibilityMatrix as ThemeCompatibilityMatrix;
pub use crate::ThemeCompatibilityRow as ThemeCompatibilityRow;
pub use crate::ThemeConfig as ThemeConfig;
pub use crate::ThemeDef as ThemeDef;
pub use crate::ThemeDefinition as ThemeDefinition;
pub use crate::ThemeDiagnosticVerbosity as ThemeDiagnosticVerbosity;
pub use crate::ThemeExplainReport as ThemeExplainReport;
pub use crate::ThemeFallbackStrategy as ThemeFallbackStrategy;
pub use crate::ThemeInteropPolicy as ThemeInteropPolicy;
pub use crate::ThemeManifestFragment as ThemeManifestFragment;
pub use crate::ThemeManifestPolicyHook as ThemeManifestPolicyHook;
pub use crate::ThemeOutputBudget as ThemeOutputBudget;
pub use crate::ThemeOutputReport as ThemeOutputReport;
pub use crate::ThemeOutputViolation as ThemeOutputViolation;
pub use crate::ThemePreset as ThemePreset;
pub use crate::ThemePresetProfile as ThemePresetProfile;
pub use crate::ThemeReducedMotion as ThemeReducedMotion;
pub use crate::ThemeReg as ThemeReg;
pub use crate::ThemeRegistry as ThemeRegistry;
pub use crate::ThemeRoutePolicy as ThemeRoutePolicy;
pub use crate::ThemeRuntimeEmission as ThemeRuntimeEmission;
pub use crate::ThemeSerializationFormat as ThemeSerializationFormat;
pub use crate::ThemeVisualTokenRole as ThemeVisualTokenRole;
pub use crate::apply_theme_manifest_hook as apply_theme_manifest_hook;
pub use crate::default_themes as default_themes;
pub use crate::explain_theme as explain_theme;
pub use crate::theme as theme;
pub use crate::theme_cache_key as theme_cache_key;
pub use crate::theme_compatibility_matrix as theme_compatibility_matrix;
pub use crate::theme_def as theme_def;
pub use crate::theme_id as theme_id;
pub use crate::theme_manifest_fragment as theme_manifest_fragment;
pub use crate::theme_native_port_hints as theme_native_port_hints;
pub use crate::theme_output_budget as theme_output_budget;
pub use crate::theme_output_report as theme_output_report;
pub use crate::theme_route_policy as theme_route_policy;
pub use crate::themes as themes;
pub use crate::integration::*;

Install

[dependencies]
dioxus-theme-core = "0.1.0-alpha.4"

What It Provides

  • Theme registries with overrideable defaults.
  • Serializable theme tokens for SSR and lazy runtimes.
  • Animation, storage, target, and reduced-motion policy configuration.
  • Built-in animation presets: fade, cross-fade, slide, radial-wipe, and masked-wave.
  • Validation for route-safe selectors, storage keys, registered defaults, and CSS token values.
  • Token-name constants such as THEME_TOKEN_BG, THEME_TOKEN_FG, and THEME_TOKEN_ACCENT.
  • Visual-token manifest metadata for Shader, HoverFX, TextFX, and other packages listening to dioxus-theme:change.

Example

use dioxus_theme_core::{
    ThemeAnimationPreset, ThemeConfig, ThemeDefinition, ThemeRegistry, THEME_TOKEN_ACCENT,
};

let brand = ThemeDefinition::new("brand", "Brand")
    .with_token(THEME_TOKEN_ACCENT, "#0f766e");

let config = ThemeConfig::default()
    .with_registry(ThemeRegistry::default().with_theme(brand))
    .with_default_theme("brand")
    .with_animation_preset(ThemeAnimationPreset::MaskedWave)
    .with_animation_speed(125)
    .with_animation_storage_key("app-theme-animation")
    .with_animation_speed_storage_key("app-theme-animation-speed");

let report = config.validate();
assert!(report.is_valid());

Animation Timing

ThemeAnimationMode controls capability and fallback behavior:

  • ViewTransition: use the View Transition API when available.
  • CssOnly: use CSS variable transitions only.
  • None: apply changes immediately.

ThemeAnimationPreset controls the visual preset independently, and animation_speed is a percentage from 25 to 300. The default easing is ease-in-out; call with_easing("linear") or another easing string to override it.

Theme View Transitions isolate route-level view-transition-name elements by default so package theme switches animate the root snapshot without reordering named route content. Call with_view_transition_name_isolation(false) only when child named View Transition elements should participate in theme switches.

Visual Tokens

Theme semantic tokens are also exported as a shared visual contract:

use dioxus_theme_core::{
    theme_visual_token_manifest, THEME_CHANGE_EVENT, THEME_TOKEN_ACCENT, THEME_TOKEN_SURFACE,
    THEME_TOKEN_TEXT,
};

let manifest = theme_visual_token_manifest();
assert_eq!(THEME_CHANGE_EVENT, "dioxus-theme:change");
assert!(manifest.tokens.iter().any(|token| token.css_var == THEME_TOKEN_ACCENT));

The runtime dispatches dioxus-theme:change with raw tokens, semantic visualTokens, visualTokenCssVars, and visualTokenManifestVersion. Shader palettes, HoverFX sand/texture effects, and TextFX gradients can update from accent, muted, surface, and text without reloading or re-reading broad DOM state.

ViewTX Interop

Enable the optional viewtx feature to copy timing and reduced-motion policy from dioxus-viewtx-core:

dioxus-theme-core = { version = "0.1.0-alpha.4", features = ["viewtx"] }
let theme_config = ThemeConfig::default().with_viewtx_timing(&viewtx_config);

Integration Recipes

Theme integrations can emit route metadata and reuse it for SSR, Strata, asset-budget reports, WorkerTown offload planning, and optimizer caches:

use dioxus_theme_core::prelude::*;

let config = theme().with_default_theme("dark");
let policy = theme_route_policy()
    .route("/settings")
    .diagnostics(ThemeDiagnosticVerbosity::Summary)
    .fallback(ThemeFallbackStrategy::StoredOrSystem);

let manifest = theme_manifest_fragment(&config, &policy);
let batch = theme_serialize_batch([(&config, policy.clone())], ThemeBatchOptions::default())?;
let budget = theme_asset_budget_bridge(&config.output_report(&policy));
let migration = theme_strata_migration_plan(&config, &policy);

assert_eq!(manifest.package, "dioxus-theme");
assert!(batch.total_bytes > 0);
assert!(budget.categories.iter().any(|category| category.name == "style"));
assert!(migration.steps.iter().any(|step| step.contains("Strata")));
# Ok::<(), serde_json::Error>(())

ThemeRuntimeIds::duplicate_ids and deduped protect generated script/style ids, theme_precomputed_css_fragments exposes reusable custom-property CSS, and theme_optimizer_artifacts returns minifier/cache-friendly artifact hashes.

License

Licensed under either of:

Repository: https://github.com/Collin-Budrick/dioxus_template