Loading the control recipes…
Every card pairs a live control with the exact markup that produced it — the demo pane and the code pane are rendered from the same string, so what you read is what runs. Scroll for buttons, sliders, text input, lists, templates, triggers, and storyboards.
How this page works
The whole gallery is examples/snippets_gallery.rs: a list of Recipe constants, each instantiated twice — once as a live UI, once as text.
One string, two panes
Each recipe's markup is parsed and spawned into the demo pane, and the very same constant fills the code pane — snippets can't drift out of date.
const RECIPES: &[Recipe] = &[
Recipe {
title: "Slider → ProgressBar",
xaml: r##"<StackPanel Spacing="8">
<Slider Minimum="0" Maximum="100" Value="{Binding volume}" Width="220"/>
<ProgressBar Minimum="0" Maximum="100" Value="{Binding volume}" .../>
<TextBlock Text="{Binding volume, StringFormat='{}volume: {0:F0}%'}"/>
</StackPanel>"##,
..
},
// ...
];
// for each recipe: instantiate the markup into the demo pane...
let doc = bevy_pf_xaml::parse(&recipe.xaml)?;
instantiate_document_env(world, wrapper, &doc, &XamlEnv::default())?;
// ...and show the SAME string in the code pane.
set_first_text(world, code_pane, recipe.xaml);One shared view-model
All cards bind to a single reflected struct — the Button and RepeatButton cards even share a counter, and the Slider drives the ProgressBar.
#[derive(Reflect, Default)]
struct Vm {
name: String, volume: f64, agreed: bool,
pick: f64, count: f64, items: Vec<String>, profile: Profile,
}
let vm = Bindable::new(Vm { volume: 40.0, /* ... */ ..Default::default() });
vm.on_command("bump", move |_world, _param| {
counter.update(|m: &mut Vm| m.count += 1.0);
});