Loading the controls playground…

Every widget here — menus, tabs, tree, data grid, the animated swatch — is XAML instantiated into Bevy ECS entities. The clock, progress bar, and swatch are driven by plain Bevy systems locating elements by x:Uid, AutomationId, and x:Name.

How it's built

Everything in this demo comes from examples/components_showcase.rs — these are its actual pieces, in build order.

1. Spawn a XAML scene with a bound view-model

The xaml! macro validates markup at compile time; spawn_xaml_bound attaches a reflected view-model as the DataContext.

let vm = Bindable::new(Vm {
    files: vec![FileRow { name: "main.rs".into(), kind: "Rust".into(), size: 1240 }, /* ... */],
});
commands.spawn_xaml_bound(xaml!(r##"<Window ...>
      <DockPanel>
        <Menu DockPanel.Dock="Top"> ... </Menu>
        <TabControl Margin="8"> ... </TabControl>
      </DockPanel>
    </Window>"##), vm);
2. Declare controls in plain WPF markup

The Lists + Data tab: ItemsSource binding, a TreeView, and a DataGrid with typed columns.

<ListBox ItemsSource="{Binding players}"/>
<TreeView>
  <TreeViewItem Header="workspace" IsExpanded="True">
    <TreeViewItem Header="crates" IsExpanded="True"> ... </TreeViewItem>
  </TreeViewItem>
</TreeView>
<DataGrid ItemsSource="{Binding files}">
  <DataGrid.Columns>
    <DataGridTextColumn Header="Name" Binding="{Binding name}" Width="2*"/>
    <DataGridTextColumn Header="Bytes" Binding="{Binding size}" Width="*"/>
  </DataGrid.Columns>
</DataGrid>
3. Drive the UI from any Bevy system

The ticking clock, progress bar, and color-cycling swatch are ordinary systems locating elements by x:Uid, AutomationId, and x:Name.

fn live_updates(time: Res<Time>, ui: PfQuery, mut texts: Query<&mut Text>,
                mut bars: Query<&mut PfProgress>, mut commands: Commands) {
    if let Some(clock) = ui.by_uid("clock.uid")
        && let Some(t) = ui.first_text_in(clock)
        && let Ok(mut text) = texts.get_mut(t) {
        text.0 = format!("clock: {:.1}s", time.elapsed_secs());
    }
    if let Some(bar) = ui.by_automation_id("LiveProgress")
        && let Ok(mut p) = bars.get_mut(bar) {
        p.value = (time.elapsed_secs() * 10.0) % 100.0;   // fill resizes itself
    }
}
4. Toolkit controls (the Toolkit tab)

Ecosystem controls every WPF toolkit ships, as first-class elements.

<ToggleSwitch Content="Wi-Fi" IsOn="True"/>
<NumericUpDown Value="5" Minimum="0" Maximum="10"/>
<RatingBar Value="3"/>
<Badge Badge="12"><Button Content="Inbox"/></Badge>
<Chip><TextBlock Text="bevy"/></Chip>
<Card><StackPanel> ... </StackPanel></Card>
<BusyIndicator IsBusy="True" BusyContent="Loading..."> ... </BusyIndicator>
<RangeSlider Minimum="0" Maximum="100" LowerValue="25" UpperValue="70"/>
<TextBox Watermark="Search..."/>
<TimePicker SelectedTime="09:30"/>
<ColorPicker SelectedColor="#3366CC"/>
<AutoSuggestBox Suggestions="Amsterdam,Athens,Berlin,Bern"/>
<PackIcon Kind="Home" Width="20" Height="20"/>  <!-- 40+ vector icons -->
<NavigationView>
  <NavigationViewItem Content="Dashboard" Icon="Home" Tag="nav-dashboard"/>
</NavigationView>
<!-- Animation tab: storyboards, visual states, behaviors -->
<EventTrigger RoutedEvent="Loaded">
  <BeginStoryboard><Storyboard>
    <DoubleAnimation Storyboard.TargetProperty="Opacity" From="0" To="1" Duration="0:0:1.2">
      <DoubleAnimation.EasingFunction><CubicEase EasingMode="EaseOut"/></DoubleAnimation.EasingFunction>
    </DoubleAnimation>
  </Storyboard></BeginStoryboard>
</EventTrigger>
<VisualState x:Name="MouseOver">
  <Storyboard><ColorAnimation Storyboard.TargetName="chrome"
      Storyboard.TargetProperty="Background" To="#FF5B8DEF" Duration="0:0:0.15"/></Storyboard>
</VisualState>
<Interaction.Triggers>
  <EventTrigger EventName="Click">
    <InvokeCommandAction Command="{Binding save}"/>
    <ControlStoryboardAction Storyboard="{StaticResource Nudge}"/>
  </EventTrigger>
</Interaction.Triggers>
// and from any system:
bevy_pf::toast::show_with(world, "Saved!", Severity::Success, 4.0);
5. Wire a menu item with an observer

The View > Vsync toggle: find by name once, observe clicks, flip real window state.

commands.entity(toggle).observe(
    |_click: On<Pointer<Click>>, mut vsync: ResMut<Vsync>| {
        vsync.on = !vsync.on;
        vsync.dirty = true;    // apply_vsync flips Window.present_mode
    },
);