Bevy Hui

Maintain robust logical structure in Bevy while swiftly iterating on designs using hot reloading. Create reusable components in the style of Web Components.

Github crates.io

Bevy_hui is my solution to create developer friendly UI for the bevy engine. It's main focus is hot reloading pseudo html to bevy_ui.

At it's core its a custom Html parser with a syntax compiler.

Bevy_hui Cheatsheet

Default nodes

Html Bevy
<template> component entry / root element
<node> Node
<image> UiImage
<button> Button
<text> Text
<slot\> component slot marker
<property name=""> template property def with fallback

Basic Values

Valid in Html Bevy
float + px/%/vw/vh/vmin/vmax Val
auto,min,max float + px/fr/flex/vh/vw/% GridTrack
all:Val axis:Val Val full:Val Val Val Val UiRect
#FFF #FFFA #FFFFFF #FFFFFFAA rgb(1,1,1) rgba(1,1,1,1) Color

Basic Style Attributes

Html valid values
position absolute, relative
display none, flex, block, grid
overflow hidden visible (xAxis yAxis)
align_self auto start flex_end stretch end flex_start
align_items default center start flex_end stretch end baseline flex_start
align_content space_evenly space_around space_between center start flex_end stretch end flex_start
justify_self auto center start stretch end baseline
justify_items default center start end baseline
justify_content center start flex_start stretch end space_evenly space_around space_between flex_start
flex_direction auto center start stretch end baseline
flex_wrap wrap no_wrap wrap_reverse
flex_grow float
flex_shrink float
flex_basis ref Val
row_gap ref Val
column_gap ref Val
grid_auto_flow row, column, dense_column, dense_row
grid_auto_rows ref GridTrack ... (array of GridTrack)
grid_auto_columns ref GridTrack ... (array of GridTrack)
grid_template_rows (5, auto)(2, 1fr).. ref GridTrack
grid_template_columns (5, auto)(2, 1fr).. ref GridTrack
grid_row auto span(u16) start_span(i16,u16) end_span(i16,u16) end(i16) start(i16)
grid_column auto start_span(5,5) end_span(5,5) end(5) start(5)
image_mode auto stretch slice: 20px tiled(scale) stretch scale tiled: bool bool scale (scale=float)
font asset path
font_color ref Color
font_size float
delay 100ms 5s
ease bevy_math::EaseFunction snake case sine_in quintic_in_out...
max_height ref Val
max_width ref Val
min_height ref Val
min_width ref Val
bottom ref Val
top ref Val
right ref Val
left ref Val
height ref Val
width ref Val
padding ref UiRect top->right->bottom->left
margin ref UiRect top->right->bottom->left
border ref UiRect top->right->bottom->left
border_radius ref UiRect top->right->bottom->left
outline Val Val Color
background ref Color
border_color ref Color
src an asset path for image nodes

Conditional Styles

transition animation in combination with ease and delay

Html style prefix valid values
hover:.. active on Interaction::Hover
pressed:.. active on Interaction::Press
active:.. active if has component UiActive

Events

Html Explanation
on_spawn called on spawning
on_press called on Interaction::Press
on_enter called on enter Interaction::Hover
on_exit called on enter Interaction::None

Special Integration Helpers

These are local to the template and cannot be referenced outside.

Html Explanation
id="my_node" id marker (Adds UiId(String) Component)
target="my_node" target marker (Adds UiTarget(Entity) Component (resolved at build)
watch="my_node" 'watch' another nodes Interaction for conditional styles

Custom tags

Any attribute marked with tag:my_value="" can be accessed on the Tag Component owned by the node. It's just a HashMap. Great for passing args in combination with events. Checkout ui example to play a custom sound, defined by a tag on enter.

Binding Functions & Custom Components


fn setup_templates(
    mut cmd: Commands,
    server: Res<AssetServer>,
    mut html_funcs: HtmlFunctions,
    mut html_comps: HtmlComponents,
) {

    // function
    html_funcs.register("hello_world", |In(entity): In<Entity>|{
        println!("hello world");
    });

    // component
    html_comps.register("panel", server.load("panel.html"));


    // component with spawn function
    html_comps.register("slider", server.load("slider.html"), |mut entity_commands|{
        entity_commands.inser(SliderState(0.));
    });

    // advanced function using tags
    html_funcs.register("play_beep", play_beep);
}

fn play_beep(
    In(entity): In<Entity>,
    tags: Query<&Tags>,
    mut cmd: Commands,
    server: Res<AssetServer>,
) {
    let Some(path) = tags
        .get(entity)
        .ok()
        .and_then(|t| t.get("source").map(|s| s.to_string()))
    else {
        return;
    };

    cmd.spawn((
        AudioPlayer(server.load(&path)),
        PlaybackSettings::ONCE,
    ));
}