About bevy-ui
A reference skill for building user interfaces with Bevy 0.19, aimed at developers working on game UI. It covers layout, interaction, text styling, focus management, accessibility labels, and static or dynamic child trees.
Key features
- 01Build Node-based UI layouts
- 02Handle button interaction states
- 03Style text with 0.19 APIs
- 04Manage input focus and accessible names
- 05Create static and dynamic child trees
Use cases
- 01Implement menus, panels, and overlays
- 02Style text in Bevy 0.19 interfaces
- 03Add keyboard focus and accessible labels
Install
Copy the command and run it in a terminal.
$
npx skills add https:/ / github.com/ chrisgliddon/ bevy-skills --skill bevy-uiAfter installing, type/bevy-uiin Claude Code to confirm it loaded.
Bundled files
References and scripts installed along with SKILL.md.
references/accessibility.mdchildren-macro.mdcolors-and-borders.mdgotchas.mdinteraction.mdlayout.mdpalettes.mdtext.mdDetails
From the project READMEBevy 0.19 — UI
When to use this skill
- Spawn
Node-based panels, buttons, labels, overlays, or menus. - Handle
Interaction::{None, Hovered, Pressed}and visual states. - Style text after the 0.19 Parley migration.
- Manage pointer-acquired
InputFocusor accessible names. - Build static trees with
children![]or dynamic trees withwith_children.
Canonical pattern
use bevy::{
input_focus::{FocusCause, InputFocus},
prelude::*,
};
fn main() {
App::new()
.add_plugins(DefaultPlugins) // includes InputFocusPlugin in 0.19
.add_systems(Startup, setup)
.add_systems(Update, style_button)
.run();
}
fn setup(mut commands: Commands, assets: Res<AssetServer>) {
commands.spawn(Camera2d);
commands.spawn((
Node {
width: percent(100),
height: percent(100),
align_items: AlignItems::Center,
justify_content: JustifyContent::Center,
..default()
},
children![(
Button,
AccessibleLabel::new("Start game"),
Node {
width: px(180),
height: px(64),
border: UiRect::all(px(3)),
border_radius: BorderRadius::MAX,
align_items: AlignItems::Center,
justify_content: JustifyContent::Center,
..default()
},
BackgroundColor(Color::srgb(0.12, 0.12, 0.15)),
BorderColor::all(Color::WHITE),
children![(
Text::new("Start game"),
TextFont {
font: assets.load("fonts/FiraSans-Bold.ttf").into(),
font_size: FontSize::Px(32.0),
..default()
},
TextColor(Color::WHITE),
)],
)],
));
}
fn style_button(
mut focus: ResMut<InputFocus>,
mut buttons: Query<
(Entity, &Interaction, &mut BackgroundColor),
(Changed<Interaction>, With<Button>),
>,
) {
for (entity, interaction, mut background) in &mut buttons {
*background = match interaction {
Interaction::Pressed => {
focus.set(entity, FocusCause::Pressed);
BackgroundColor(Color::srgb(0.15, 0.55, 0.25))
}
Interaction::Hovered => BackgroundColor(Color::srgb(0.22, 0.22, 0.28)),
Interaction::None => BackgroundColor(Color::srgb(0.12, 0.12, 0.15)),
};
}
}
Topics
| Topic | Reference |
|---|---|
Node, Val, flex/grid layout | Layout |
FontSource, FontSize, TextLayout | Text |
Button, Interaction, Changed | Interaction |
| Colors, borders, and radii | Colors and borders |
| Palette constants | Palettes |
InputFocus, semantics, accessible labels | Accessibility |
| Static and dynamic children | Children |
| Cross-cutting traps | Gotchas |
Gotchas
- A newly inserted component satisfies
Changed<T>. The interaction system normally visits a new button on its firstUpdate; useRef<T>::is_added()when insertion and later mutation must be distinguished. - Pointer hover and input focus are different. Do not move or clear keyboard / assistive-technology focus merely because the cursor entered or left.
TextFont.fontisFontSource; convert aHandle<Font>with.into().font_sizeisFontSize, such asFontSize::Px(32.0).InputFocusfields are private. Useget,set(entity, FocusCause), andclear.DefaultPluginsinitializes it.- A visible text child gives a
Buttonan inferred name, but useAccessibleLabelwhen the visual text is absent, decorative, or ambiguous.
See also
bevy-a11y— full game accessibility implementation.bevy-fluent— localized UI text.bevy-cameras— UI cameras and render targets.bevy-ecs-queries— change detection.
Comments
Markdown supported