Commit Graph

40 Commits

Author SHA1 Message Date
Jeb Brooks ea06f80230 Optionally allow FeathersColorSwatch to partially display opaque value (#24639)
This adds properties to the `FeathersColorSwatch` SceneComponent to
allow specifying a percentage of the swatch to remain opaque. This is
useful for color-pickers and generally handling colors with alpha
channels.

The property value will default to 0% so no migration guide is needed.

# Objective

- Allow a single `FeathersColorSwatch` to display the selected color
with and without its alpha channel.

## Solution

- Adds `FeathersColorSwatchProps` to allow dedicating a percentage of
the swatch area to the opaque color value

## Testing

Updated the `feathers_gallery` example to display the `rgba` color
swatch with 30% dedicated to the opaque color.

---

## Showcase

<img width="1280" height="720" alt="Screenshot_2026-06-15_21-09-53"
src="https://github.com/user-attachments/assets/1b3405f5-973b-42fb-abd5-b08c39c59cb6"
/>
2026-06-17 05:18:25 +00:00
Talin 6588a8e7ef Modal dialog box for feathers (#24559)
# Objective

Part of #19236 

## Solution

Modal Dialog boxes

## Testing

Manual testing in feathers gallery

## Showcase

<img width="386" height="210" alt="feathers_dialog"
src="https://github.com/user-attachments/assets/9759db07-e1f6-4497-bc73-c8bb05798b1d"
/>
2026-06-09 00:51:04 +00:00
Talin 9a35b6a237 Feathers scrollbar and list view. (#24092)
# Objective

Part of #19236 

## Solution

Implementation of scrollbars and list views for Feathers.

## Testing

Manual testing:
* click to select
* wheel scrolling
* tab and keyboard navigation

## Showcase

<img width="380" height="182" alt="listbox"
src="https://github.com/user-attachments/assets/d3f902cd-0c73-475f-806b-d6ccb5ea3cac"
/>

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2026-06-07 02:10:38 +00:00
Carter Anderson c516bd8f48 bsn: support inline macros in field value position (#24524)
# Objective

`bsn!` currently requires surrounding macros in "field value position"
with `{}`:
```rust
bsn! {
  Foo { value: {vec![ 100, 200 ]} }
}
```
This is annoying!

## Solution

Support macros in field-value-position:

```rust
bsn! {
  Foo { value: vec![ 100, 200 ] }
}
```

## Testing

- Added a test that checks that this works
- Ported bsn! examples to use this
2026-06-04 00:28:58 +00:00
laund 9ed66d7a06 bsn: throw error when using caching syntax on unsupported scene entries (#24473)
# Objective

Implement changes discussed with cart around erroring when using caching
syntax where its not implemented.


## Solution

Throw a compile error, in a way which is easy to remove once caching
exists/works for more cases.

Also contains a commit to alleviate trait errors which will (from my
experience writing this PR and fixing them in bevy) arise from fixing
this for existing bsn code. This commit can be dropped if not desired.
This would ideally be fixed upstream so this workaround can be removed:
https://github.com/rust-lang/rust/issues/141258#issuecomment-4565897810

Note: The error caused by this workaround is far from ideal. It
initially looks like a method call is missing, but ultimately the
hint/advice *is* correct
<img width="1982" height="477" alt="image"
src="https://github.com/user-attachments/assets/879f7630-ada8-4e63-9c59-80be466f37cf"
/>


## Testing

- `cargo test -p bevy_scene --lib`
- `cargo check`

---------

Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2026-05-29 23:07:39 +00:00
Doonv 3f401d1507 Update examples to use Image::new_target_texture instead of manual image creation when possible (#23715)
# Objective

Fix #19101. (Kinda, this is not the exact solution proposed in that
issue, but it still shortens most of the examples)

## Solution

Most of the images created in examples are for use in render targets.
`Image::new_target_texture` is made for exactly that and significantly
shortens the image creation process.

## Testing

I tested all the examples I changed and they seem to work fine.

--- 

btw for some reason most of the examples use
`TextureFormat::Bgra8UnormSrgb` while the documentation for
`Image::new_target_texture` recommends `TextureFormat::Rgba8UnormSrgb`
for SDR images. What's up with that?

---------

Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2026-05-22 14:33:16 +00:00
laund 5897ed605b BSN: changing prefixes for Template and SceneComponent to allow removing confusing "inheritance" concept (#24367)
# Objective

Changes discussed with cart:
- `:` will not be called "inheritance" anymore, but instead "cacheable"
(name not final)
- the Template patching prefix changes `@` -> `~`
- the SceneComponent prefix changes `:` -> `@`
- the `:` prefix is allowed in front of `@SceneComponent` as well,
marking it as being cached

>> me: do we forbid caching of functions which take an argument?

> cart: We should forbid it until we support it, and I don't plan on
supporting this in the short term, as it adds new controversial design
aspects to the system (building a mapping from parameters to cached
scenes, ensuring the parameters are all hashable, etc).

Link to the discord thread, specifically my [recap
message](https://discord.com/channels/691052431525675048/1264881140007702558/1506422311056576702).

The exact reasoning is in the linked discord discussion, but the tldr
is:
"Inheritance" as a term for the ":" syntax didn't really fit what bsn
was doing, since scenes without `:` produce the same result. All `:` is,
is a way to say "cache this pls" with the design of bsn imposing the
limitation that only the first scene can be cached

That was all fine, except for one case: Disambiguating SceneComponents
from normal components. So if we redefine `:` to just mean "caching" we
needed to untangle it from SceneComponents. That means disambiguating
SceneComponents needed a different syntax, and the decision ended up
being to take the @ prefix from the *much* less common `@Template`
usecase, since `SceneComponent {@prop: val}` already used @ as well and
introduce a new prefix to replace `@Template` instead, replacing it with
`~Template`.

## Solution

Implement these changes in macros.

Notably, this *still* doesn't implement/enable caching right now.  

Most docs are updated, except for the big blocks in
`bevy_scene/src/lib.rs` and `bevy_scene/macros/src/lib.rs` since i've
been working on reworking those on another branch and didn't want to
duplicate whats already been a lot of work and likely to be a bunch more

## Testing

- [x] `bevy_scene` tests passing
- [x] `cargo check --workspace` and `cargo check --workspace --examples`
passing

Since this PR does not yet enable caching, I think passing the current
tests should be enough.

---------

Co-authored-by: Carter Anderson <mcanders1@gmail.com>
Co-authored-by: François Mockers <francois.mockers@vleue.com>
2026-05-21 15:37:35 +00:00
Talin 8b67e34536 Introduce AccessibleLabel component. (#24308)
See release notes for rationale and usage.

Fixes #17644, #20524

(It may not be a 100% fix, but it's good enough to close the ticket I
think.)

## Testing

- Manual testing with VoiceOver on MacOS (note that VoiceOver /
AccessKit does not work well without `desktop_app` being set, but this
causes other issues)

---------

Co-authored-by: Richard Braakman <rebraakman@gmail.com>
2026-05-21 07:56:13 +00:00
Carter Anderson abc6c9049b Feathers bsn! style improvements (#24063)
Use our "shorthand" conventions for `Val` everywhere in feathers code /
usage

This also:
- adds a `VariantDefaults` derive to `Visibility` to make it usable
without `template_value`
- adds `From<Val>` to BorderRadius to support `px(10)` assignments
instead of `BorderRadius::all(px(10))`

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: ickshonpe <david.curthoys@googlemail.com>
2026-05-04 03:11:02 +00:00
Talin d03f0c7dc1 Renamed ToolButton to FeathersToolButton to be consistent (#24098)
with naming conventions for other widgets.

# Objective

The `ToolButton` widget was not consistently named like the other
controls.

## Solution

Renamed.

## Testing

Basic manual testing.

@cart
2026-05-03 23:54:17 +00:00
Alice Cecile ba7b3c8950 Rename bevy_experimental_feathers feature to bevy_feathers (#24108)
# Objective

> With the introduction of scene components, the feathers API has now
reached its final form. This has a number of consequences:
> - There's no longer any reason to keep the experimental flag around
> - The effort of migrating the Bevy examples to feathers widgets is
unblocked, however I think we should start with migrating just one
example


- @viridia 

## Solution

1. Rename the feature flag.
2. Write a migration guide.

This was previously attempted as part of
https://github.com/bevyengine/bevy/pull/22934, but I got pushback there.
Now that bsn! is more complete (scene components!) things are better.

I've opted not to change the default features here, even though it makes
it much harder to move our examples over, because that's a much more
contentious change. While I feel that Bevy's default features should be
example-oriented, that's still up for debate!
2026-05-03 23:53:51 +00:00
Carter Anderson aadbf46184 Scene Components (#24008)
# Objective

It is essentially a Bevy rite of passage to define a `Player` component
and then ask "ok when I spawn `Player`, how do I spawn all of the other
entities / components / scenes it needs to function with it?".

In Bevy, components are the "unit of behavior". The presence of a
component indicates that the entity should behave a certain way. Scenes
are _inextricable_ from behaviors, yet currently there is no way to tie
Components (bevy's unit of behavior) to scenes. _This is a fundamental
gap in the Bevy data model_. It is a problem that developers expect
their engine to solve for them.

It is high time that we had an official solution to this problem. BSN
was built to be that solution, and it is now time to do the last-mile
work to facilitate the `Component <-> Scene` relationship

## Solution

It is now possible to define "scene components", where `SceneComponent:
Component`:

```rust
#[derive(SceneComponent, Default, Clone)]
struct Player {
    score: usize
}

impl Player {
    fn scene() -> impl Scene {
        bsn! {
            Transform { translation: Vec3 { x: 10. } }
            Children [
                LeftHand,
                RightHand,
            ]
        }
    }
}
```

This enables inheriting from the Player component as a scene:

```rust
world.spawn_scene(bsn! {
    :Player { score: 0 }
})
```

After the inherited `Player` scene component is spawned, the _entire_
scene is available. This means that you can `Query<&Player>` in your ECS
systems, and _trust_ that the entire scene is also present.

### Inheritance Syntax vs Patch Syntax

Notice that this uses inheritance syntax in BSN (`:`), rather than
normal "component patch" syntax (ex: `bsn! { Player { score: 0 } }`.
Semantically these are different things:
- Scene inheritance syntax: constructs the full scene and inherits from
it
- Component patch syntax: _Just_ patches the component directly and
creates it if it doesn't exist. This will not do any scene inheritance.
You can still patch scene components this way as long as the scene
component is inherited somewhere "earlier" in the inheritance hierarchy.

Attempting to spawn a scene component on its own _without_ the scene
(ex: `commands.spawn(Player::default())`) will log an error, as Scene
Components should never exist without their scene.

### Custom Scene Functions

When deriving `SceneComponent`, it defaults to using `Self::scene` as
the "scene function". Scene functions can also be manually specified:

```rust
#[derive(SceneComponent, Default, Clone)]
#[scene(player)]
struct Player {
    score: usize
}

fn player() -> impl Scene {
   bsn! { /* scene here */}
}
```

### Inherit BSN Asset Paths

Alternatively, a scene asset path can be specified:

```rust
#[derive(SceneComponent, Default, Clone)]
#[scene("player.bsn")]
struct Player {
    score: usize
}
```

Once we port the glTF loader to BSN, this will also be supported:
```rust
#[derive(SceneComponent, Default, Clone)]
#[scene("player.gltf")]
struct Player {
    score: usize
}
```

### Scene Props

Sometimes it is desirable to "parameterize" a scene: pass in values to
the scene which determine what the scene outputs are.

The answer to this in BSN is "scene props":

```rust
/// A UI widget that repeats "hello" text a given number of times.
#[derive(SceneComponent, Default, Clone)]
#[scene(HelloRepeaterProps)]
struct HelloRepeater;

#[derive(Default)]
struct HelloRepeaterProps {
    repeat: usize,
}

impl HelloRepeater {
    fn scene(props: HelloRepeaterProps) -> impl Scene {
        let hellos = (0..props.repeat)
            .map(|_| bsn!{ Text("hello") })
            .collect::<Vec<_>>();
        bsn! {
            Node
            Children [
                {hellos}
            ]
        }
    }
}

world.spawn_scene(bsn! {
   :HelloRepeater {
       @repeat: 5
   } 
});
```

Notice the `@field` syntax, which specifies that a prop is being set
instead of a field. Props are evaluated "immediately" at the point of
inheritance where the scene is constructed. This means that they are not
"patchable".

You can set _both_ props and normal fields at the same time:

```rust
#[derive(SceneComponent, Default, Clone)]
#[scene(WidgetProps)]
struct Widget {
    value: usize
}

#[derive(Default)]
struct WidgetProps {
    border: bool,
}

world.spawn_scene(bsn! {
   :Widget {
       @border: true,
       value: 10,
   } 
});
```

Scene props can be used with templates:

```rust
#[derive(SceneComponent, Default, Clone)]
#[scene(PlayerProps)]
struct Player;

#[derive(Default)]
struct PlayerProps {
    head: AssetPath<'static>,
    body: AssetPath<'static>,
}

impl Player {
    fn scene(props: PlayerProps) -> impl Scene {
        bsn! {
            Transform
            Visibility
            Children [
                (Head, Sprite { image: {props.head} }),
                (Body, Sprite { image: {props.body} }),
            ]
        }
    }
}

world.spawn_scene(bsn! {
   :Player {
       @head: "big_head.png"
       @body: "small_body.png"
   } 
});
```

### Scene Components are Template-able

```rust
#[derive(SceneComponent, FromTemplate)]
struct Player {
    image: Handle<Image>,
}

impl Player {
    fn scene() -> impl Scene {
        bsn! { /* scene here */}
    }
}

world.spawn_scene(bsn! {
   :Player { image: "player.png" } 
});
```


### The Scene Component is Always Added

Specifying the scene component manually in the scene function is not
necessary. It will be added automatically:

```rust
#[derive(SceneComponent, Default, Clone)]
struct Player {
    score: usize
}

impl Player {
    fn scene() -> impl Scene {
        bsn! {
            // No need to specify a Player component here.
            // It is implied!
        }
    }
}
```

However you _can_ patch the scene component in the scene if you would
like. This comes in handy if you would like props to contribute to the
scene component's value:

```rust
impl Player {
    fn scene(props: PlayerProps) -> impl Scene {
        bsn! {
            Player {
                size_in_meters: {props.size_in_millimeters / 1000. }
            }
        }
    }
}
```

### SceneComponent Trait

This is what SceneComponent looks like under the hood:

```rust
pub trait SceneConstructor: FromTemplate<Template: Default>
where
    <Self::Template as Template>::Output: Component,
{
    type Props: Default;
    fn scene(props: Self::Props) -> impl Scene;
}
```

In general, developers should prefer `#[derive(SceneComponent)`, which
derives this trait automatically, ensures the Component is never spawned
without its scene, and automatically initializes the `Component` even if
it isn't specified explicitly in the user-defined scene function.

### Reusable Component Derive Logic

This PR moves the component derive logic into a new
`bevy_ecs_macro_logic` crate and refactors it to be reusable and
extendable.

This enables the `SceneComponent` derive to reuse and configure the
`Component` derive. I also took the liberty of porting the redundant
`Resource` derive logic to this system, as it follows the same pattern.

## PR Todo

- [ ] Port this PR description to docs on `Scene`.

## Whats Next

- Scene Component scene caching: It might make sense to cache
unparameterized scenes (like we do for scene assets) to cut down on
spawn costs. We could even have an opt-in parameterized scene cache (ex:
hash the props).
- Reactivity: It is important to note that props _are not reactive_.
They do not exist post-spawn (aka "at runtime") and they cannot be
changed. However they could easily be _part_ of a reactivity story:
- Props as components: insert props as components and re-run the scene
constructor when they are mutated
- Signal props: Reactive "signal" types could be passed down the init
hierarchy via props.
- Simpler "prop patching" codegen: currently for simplicity props reuse
the template-patching logic, but this introduces a few constraints and
complexities that are unnecessary. We should consider writing
specialized logic for them.
2026-05-01 21:07:22 +00:00
ickshonpe 1ed78a2a52 Fix feathers gallery button info (#24062)
# Objective

The `feathers gallery` example logs "Disabled button clicked!" when its
"Primary" button is clicked.

## Solution

Log "Primary button clicked!" instead.
2026-05-01 21:02:34 +00:00
Jordan Halase 1dac2eca81 Add cause field to FocusGained event (#23993)
# Objective

- Users would like the ability to know how a focus was gained

## Solution

- Add `FocusCause` field to `FocusGained` event
- Automatically select all when navigating into a text input (even
without `SelectAllOnFocus`)

## Testing

- Tab into the color input of `feathers_gallery` to test that its text
gets highlighted
2026-04-26 23:08:46 +00:00
Alice Cecile 8623d29a7a Remove Core prefix from remaining UI widget components (#23938)
# Objective

This prefix was ruled unhelpful, and we previously removed it from most
of our types.

We missed a few apparently (spotted in #23924).

## Solution

Find and replace + update the migration guide.
2026-04-22 19:56:27 +00:00
Talin 64fe756adb Number input (#23842)
# Objective

Part of #19236 

## Solution

A numeric text input widget. This includes:

* Colored stripes ("sigils") for designating X, Y and Z input fields.
* Character filtering
* ValueChange events

Not supported:

* Validation error events
* Range and precision options

Additional changes in this PR:

* Added small labels (related to text inputs only insofar as numeric
inputs have small labels above them in the editor design).
* Refactored labels to be simple spans instead of nested entities - this
required a non-inherited text font theme component, so we renamed the
existing component to have the word "inherited" in the name.
* Consolidated the way focus outlines work for text inputs and other
widgets
* I had to make changes to Slider and other widgets to support the
`is_final` flag in `ValueChange`. This is necessary to allow listeners
the choice between spammy and not-spammy updates when listening to
widget outputs.

## Testing

Manual testing

## Showcase

<img width="353" height="101" alt="numeric_input"
src="https://github.com/user-attachments/assets/36efd243-fa01-484e-bab5-689aa6be4d9e"
/>
2026-04-21 05:47:05 +00:00
Jordan Halase 9eed7a39a1 Fix Feathers radio groups, add radio_self_update() (#23890)
# Objective

No helper nor example code exists for handling multiple radio button
groups. Currently if a user tries to use existing feathers_gallery code
to create multiple radio groups, radio buttons from all other groups
will become unchecked.

## Solution

- Within queries, only update the radio buttons inside their own group
- Add `radio_self_update()` convenience function to encapsulate this
desired behavior

## Testing

Manually tested inside feathers_gallery example
2026-04-20 05:08:41 +00:00
Carter Anderson aa5322ed0f BSN: scene.spawn() system ergonomics (#23868)
# Objective

Spawning a scene on startup is a common pattern. Lets make it easier to
do so!

## Solution

- Add `SpawnSystem` and `SpawnListSystem` traits that are implemented
for functions that return scenes / scene lists, and return a system that
spawns the scene / handles errors.

### Before
```rust
fn main() {
    App::new()
        .add_plugins(DefaultPlugins)
        .add_systems(Startup, setup)
        .run();
}

fn setup(world: &mut World) -> Result {
    world.spawn_scene_list(bsn_list![Camera2d, ui()])?;
    Ok(())
}
```

### After
```rust
fn main() {
    App::new()
        .add_plugins(DefaultPlugins)
        .add_systems(Startup, scene.spawn())
        .run();
}

fn scene() -> impl SceneList {
    bsn_list![Camera2d, ui()]
}
```

This cuts out some boilerplate. It also further encourages people to
define standalone "scene functions" rather than embedding them in code,
which is generally a good pattern.
2026-04-19 17:25:21 +00:00
Jordan Halase 6af4a0329c Fix toggle behavior and add styling to Feathers Radio Buttons (#23869)
# Objective

Continuation of https://github.com/bevyengine/bevy/pull/23820 and
https://github.com/bevyengine/bevy/pull/23830

This fixes the clicking behavior to toggle on mouse-release, or on
mouse-press with the `ActivateOnPress` component. More styling tokens
are also added for transition states.

---

## Showcase

### Before

<img width="91" height="91" alt="Screenshot 2026-04-17 at 11 32 39 PM"
src="https://github.com/user-attachments/assets/b1b8832d-7aaa-45ee-a641-4c100d44a232"
/>

### After

<img width="91" height="91" alt="Screenshot 2026-04-17 at 11 13 33 PM"
src="https://github.com/user-attachments/assets/d3cf5bf6-1dfe-4d88-8dd1-fc719449e7b5"
/>

(Not pictured: new intermediate styling for mouse press)

---------

Co-authored-by: François Mockers <francois.mockers@vleue.com>
2026-04-19 15:56:24 +00:00
Rob Parrett d4379d437d Revert unintended example changes (#23877)
# Objective

Fixes #23873

## Solution

Partial git revert

## Testing

I did not test
2026-04-18 17:19:09 +00:00
ickshonpe bb1d51623b Fix UI accessibility transforms and update ordering (#23859)
# Objective

* Bevy UI's accessibility module doesn't set the transform on
accessiblity nodes, ignoring scaling and rotation.
* UI accessibility nodes should be updated before `bevy_winit` updates
the accesskit adaptors, otherwise there will be a frames delay.


## Solution

Replaced the `calc_bounds` systems with a new system
`sync_bounds_and_transforms`.

Each accesskit `Node` corresponding to an `AccessibleNode` UI entity is
now given object-centered coordinates for its bounding rect (instead of
window coordinates) and a transform.

Accesskit uses local transforms so if an accessible node also has an
accessible parent, its transform has to be recomputed relative to its
parent.

## Testing

I modified the button example so that accesskit integration is enabled
by default and the button is drawn at a 45 degrees angle.

```
cargo run --example button
```

Screen readers should only react when the pointer is directly over the
rotated button if the changes are working.

The example changes should be reverted before merging.
2026-04-18 04:35:53 +00:00
ickshonpe 4c7e99cc56 feathers_gallery infinite update loop fix (#23827)
# Objective

In the `feathers_gallery` example, on a `TextEditChange`
`handle_hex_color_change` updates `DemoWidgetStates` which causes
`update_colors` to update the hex input triggering another
`TextEditChange`.

## Solution

Only update `DemoWidgetStates` in `handle_hex_color_change` if the new
color is different.
2026-04-17 15:57:02 +00:00
Jordan Halase 6c867fa44a Fix and Polish Feathers Toggle Switch (#23830)
# Objective

This is a continuation of https://github.com/bevyengine/bevy/pull/23820
for toggle switches to fix their clicking behavior and add more style
tokens. Again, adding the `ActivateOnPress` component will change its
state instantly on mouse-press rather than mouse-release.

Styling is also changed for visibility and disambiguation.

---

## Showcase

### Before

<img width="120" height="31" alt="Screenshot 2026-04-16 at 1 53 12 PM"
src="https://github.com/user-attachments/assets/22fd0374-76cb-40bb-9428-cbd7c69f2e50"
/>

### After

<img width="159" height="31" alt="Screenshot 2026-04-16 at 3 32 21 PM"
src="https://github.com/user-attachments/assets/ecb5bee6-0dbd-4598-8487-cdb333575f78"
/>

(Not pictured: new intermediate styling for mouse press)
2026-04-17 02:37:18 +00:00
Talin 6b4a003428 Disclosure toggle widget. (#23817)
# Objective

Part of #19236 

The "disclosure toggle" is a small checkbox-like widget which displays a
chevron that toggles between pointing right and pointing down.

## Testing

Manual testing
2026-04-16 04:39:26 +00:00
Jordan Halase e677babe59 Fix and Polish Feathers Checkbox (#23820)
# Objective

* Fix toggle behavior
* Add more style tokens and polish appearance

The original intention for the Feathers Checkbox was to toggle the
change immediately on mouse press, but currently only toggles on mouse
release, and lacks styling. Both behaviors are desirable depending on
context, such as being able to cancel an expensive checkmark click that
vastly changes render settings, so this pull request allows both, with
the mouse-press behavior enabled via the `ActivateOnPress` component.

In addition to adding styling, there will no longer a visible outline
for the checkbox in the checked state in the default theme. Having a
border and check symbol made it visually busy, especially at small
sizes.

---

## Showcase

### Before

<img width="161" height="83" alt="Screenshot 2026-04-15 at 7 58 09 PM"
src="https://github.com/user-attachments/assets/9cae7bcf-0b2a-46db-954a-b09332a7b06f"
/>

### After

<img width="161" height="108" alt="Screenshot 2026-04-15 at 8 34 57 PM"
src="https://github.com/user-attachments/assets/72d5083f-20db-45cd-8c1b-1ee711fcedf3"
/>

(Not pictured: new intermediate styling for mouse press)
2026-04-16 02:12:07 +00:00
ickshonpe 250a7c0e50 EditableText::visible_width (#23717)
# Objective

Horizontal equivalent of the `visible_lines` option.

Allow users to set the width of a text input widget by number of glyphs.
Or for proportional fonts, where the glyph widths are non-uniform, it
would use a multiple of the advance width for "0".

## Solution

* New `visible_width: Option<f32>` field on `EditableText`.
* `TextInputMeasure` now has both a width and height field and both are
`Option<f32>`.
* `update_editable_text_content_size` calculates the width if
`visible_width` is `Some`.
* The width is calculated by multiplying the advance width of "0" by the
`visible_width` (if set) and the current scale factor.

## Testing

I altered the hex input in the `feathers` example to so it's sized to
fit 10 characters (includes space for the cursor).

```
cargo run --example feathers --features="experimental_bevy_feathers"
```

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2026-04-15 17:02:41 +00:00
Talin 574e9356cb Decorative widgets (#23804)
# Objective

Part of #19236 

## Solution

A bunch of new, decorative widgets - see release note.

## Testing

Manual testing

## Showcase

<img width="384" height="207" alt="panes"
src="https://github.com/user-attachments/assets/0b0bb2ee-d520-4280-938e-e08d5c4e49d1"
/>

---------

Co-authored-by: Kevin Chen <chen.kevin.f@gmail.com>
2026-04-15 15:42:55 +00:00
Talin 4553e66916 Add menu_divider widget. (#23788)
# Objective

Menu dividers have been requested by the editor ui design folks.

## Solution

A new `menu_divider` bsn function

## Testing

Manual testing

## Showcase

<img width="103" height="120" alt="menu_divider"
src="https://github.com/user-attachments/assets/382eb57b-732d-454b-a0df-96ebcc39df97"
/>
2026-04-14 03:13:49 +00:00
Talin f1a6b878ab Change feathers bsn APIs to make captions an explicit parameter. (#23787)
# Objective

As discussed in [this discord
thread](https://discord.com/channels/691052431525675048/1492688648360165406),
using the `Children` relation to append caption elements to feathers
widgets is dodgy.

## Solution

Make `caption` an explicit parameter for button, radio, and checkbox
widgets.

Also fixed some erroneous docs.

## Testing

Manual testing of feathers and bevy_city examples.

Note that there's no migration guide because this only affects the bsn
functions, which are new.
2026-04-13 23:48:40 +00:00
IceSentry 78cc3bc98c Add feathers_counter (#23756)
# Objective

- The feathers example is more a gallery than a simple introduction to
feathers.
- We need a simple example to introduce people to feathers

## Solution

- Add a simple counter that uses feathers

## Testing

I ran the example on my machine

---

## Showcase


https://github.com/user-attachments/assets/4e827e9a-aed9-4c23-918e-05464a5ada67

It doesn't look super great so any styling suggestion is appreciated.

---------

Co-authored-by: Kevin Chen <chen.kevin.f@gmail.com>
2026-04-13 21:16:26 +00:00
Talin ba9d7a39bc Menu button (#23707)
# Objective

Dropdown menus and menu buttons for feathers.

Part of #19236 

## Solution

This implements a feathers widget for dropdown menus, including:

* Keyboard navigation (Enter, Space, Arrow Keys, Escape)
* Tab focus
* Accessibility
* Click outside to cancel
* Items highlight on hover and press

## Testing

Manual testing

## Showcase

<img width="402" height="119" alt="feathers_menu"
src="https://github.com/user-attachments/assets/58a8e9d1-f443-4da2-b828-54f2d0237df4"
/>
2026-04-12 20:44:38 +00:00
Alice Cecile ffa4b0e8d9 Add FocusGained and FocusLost entity events (#23723)
# Objective

When working with more complex widgets, users have repeatedly asked for
a way to reliably detect when an entity gains or loses focus. They have
not, however, filed an issue about this 🎟️

These are called
[`focus`](https://developer.mozilla.org/en-US/docs/Web/API/Element/focus_event)
/
[`focusin`](https://developer.mozilla.org/en-US/docs/Web/API/Element/focusin_event)
+
[`blur`](https://developer.mozilla.org/en-US/docs/Web/API/Element/blur_event)
/
[`focusout`](https://developer.mozilla.org/en-US/docs/Web/API/Element/focusout_event)
on the web. The former element in these pairs does not bubble, while the
latter does.

Because Bevy's observer infrastructure allows you to get the original
target of a bubbled event, we can create only bubbling variations.

@viridia has suggested that
https://github.com/bevyengine/bevy/pull/23707 would benefit from a form
of this feature.

## Rejected designs

The simplest approach would be to simply add a `previously_focused`
field on `InputFocus`, and then emit events based on the difference
using an ordinary system. Unfortunately, this has a serious flaw: events
are lost if this changes state multiple times in the same frame.

We can resolve this problem by completely locking down access, and
requiring commands or events to be used to change the input focus. This
ensures no changes are lost and sends them off semi-immediately, but is
a major breaking change to this API and prevents immediate-mode checks
of "what is the current input focus".

## Solution

We can do better. If we sacrifice "FocusGained and Lost must be emitted
immediately", we can track changes inside of `InputFocus`, before
sending them off in an ordinary system.

This is minimally breaking (you have to use the getters/setters now),
and ensures no gained/lost events are ever missed. Users who completely
overwrite `InputFocus` (e.g. by using `from_entity`) will miss changes,
but frankly, you deserve it if you ignore the nice setters and clear
warnings in the docs.

- Define `FocusGained` and `FocusLost` events. Split to their own file
for cleanliness.
- Lock down access to `InputFocus`, forcing users to always go through
the existing getters and setters.
- Modify `InputFocus` to track changes as they have been made.
- Add a system to drain these once-per-frame in `PostUpdate`, converting
them into `FocusGained` and `FocusLost`.
- This timing helps ensure that any user / library code that changes the
focus has time to run, but rendering code that relies on accurate focus
information to display widgets has the information available.
- I could not find existing systems in `PostUpdate` that this needed a
relative ordering for.
- Create an `InputFocusPlugin` to store this new system, stealing some
of the setup that was previously in `InputDispatchPlugin`. Somewhat
incidentally, this fixes #19057, by selecting option 1.

## Testing

I was *not* very confident that my implementation of this logic was
correct, so I wrote a rather aggressive set of mid-level tests, using
`App`.

They pass, so apparently my first implementation was actually good
enough.
2026-04-10 06:53:00 +00:00
Talin 8f251ffcb4 Feathers text input widget (#23645)
# Objective

Feathers text input widget
Part of #19236 

## Solution

Build a wrapper around `EditableText` that has feathers styling and
themes.

## Testing

WiP

---------

Co-authored-by: Kevin Chen <chen.kevin.f@gmail.com>
2026-04-07 18:28:48 +00:00
Carter Anderson 6b0fb37e2c Rename bevy_scene2 to bevy_scene (#23668)
# Objective

Part 3 of #23619 

## Solution

Renames `bevy_scene2` to `bevy_scene` and adds it to the prelude.
2026-04-05 02:19:43 +00:00
Luke Yoo 09ef09eaa5 UiWidgetsPlugins and InputDispatchPlugin are now in DefaultPlugins (#23346)
# Objective

-
[Overview](https://hackmd.io/@UrWywBGGTV6bLjORZhuuPw/BJNPlNCu-g#Overview)
- `UiWidgetsPlugins` is part of `DefaultPlugins`
- Prerequisite for [Remove `Interaction` from
`examples/*`](https://github.com/bevyengine/bevy/pull/23285)

## Solution

- `UIWidgetsPlugins` adds `InputDispatchPlugin`.
- `UIWidgetsPlugins` and `InputDispatchPlugin` are removed from
`FeathersPlugins`.
- `UIWidgetsPlugins` slips into `DefaultPlugins`.

## Testing

Following examples are relevant:
- examples/ui/widgets/feathers.rs
- examples/games/game_menu.rs

## Also

[Migration
Guide](https://github.com/micttyoid/bevy/blob/ui-widgets-to-default-2/_release-content/migration-guides/ui_widgets_plugins_and_input_dispatch_plugin_are_now_default.md)
- Also: e7bab9fb83

[TODO after merge](#issuecomment-4057934697)

---------

Co-authored-by: Kevin Chen <chen.kevin.f@gmail.com>
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: ickshonpe <david.curthoys@googlemail.com>
2026-04-02 18:46:41 +00:00
Carter Anderson d06aa47744 Port Bevy Feathers to BSN (#23536)
# Objective

Now that BSN is on main, we can port Feathers over!

Related: #23030 #23413

## Solution

Port Feathers, leaving the bundle functions around (renamed to
`x_bundle` and deprecated). This is largely 1:1, other than removing
HandleOrPath (which is filling the same role as HandleTemplate). I've
also ported the `feathers` and `virtual_keyboard` examples to BSN.

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2026-04-01 06:43:26 +00:00
ickshonpe 84be6ac40c Reposition Popovers in PostLayout using UiGlobalTransform. (#23587)
# Objective

Reposition `Popovers` in `PostLayout` using `UiGlobalTransform`.
 
Related: https://github.com/bevyengine/bevy/pull/23346

## Solution

* Move `popover_system` into the `PostLayout` system set.
* Reposition `Popovers` in `PostLayout` using `UiGlobalTransform`.
* Updates are immediate, so removed the trick with visibility.

## Testing

```
cargo run --example standard_widgets
```

The pop up menu still seems to work anyway.
2026-03-30 22:31:11 +00:00
moktamd e8ca3850a6 Add SliderOrientation to control slider axis detection (#23310)
The `Slider` widget auto-detects orientation based on dimensions
(vertical if height > width). This causes the Feathers slider to behave
as vertical when its layout happens to be taller than wide, while its
visuals (gradient direction, cursor icon) are hardcoded as horizontal.

Adds a `SliderOrientation` enum (`Auto`/`Horizontal`/`Vertical`) to give
explicit control. Sets the Feathers sliders to `Horizontal` so their
interaction matches their presentation.

Fixes #23294

---------

Co-authored-by: moktamd <moktamd@users.noreply.github.com>
2026-03-11 21:27:30 +00:00
ickshonpe 6ca4769128 Minimal responsive FontSize support (#22614)
# Objective

Add responsive font sizes supporting rem and viewport units to
`bevy_text` with minimal changes to the APIs and systems.

## Solution

Introduce a new `FontSize` enum:

```rust
pub enum FontSize {
    /// Font Size in logical pixels.
    Px(f32),
    /// Font size as a percentage of the viewport width.
    Vw(f32),
    /// Font size as a percentage of the viewport height.
    Vh(f32),
    /// Font size as a percentage of the smaller of the viewport width and height.
    VMin(f32),
    /// Font size as a percentage of the larger of the viewport width and height.
    VMax(f32),
    /// Font Size relative to the value of the `RemSize` resource.
    Rem(f32),
}
```

This replaces the `f32` value of `TextFont`'s `font_size` field.

The viewport variants work the same way as their respective `Val`
counterparts.

`Rem` values are multiplied by the value of the `RemSize` resource
(which newtypes an `f32`).

`FontSize` provides an `eval` method that takes a logical viewport size
and rem base size and returns an `f32` logical font size. The resolved
logical font size is then written into the `Attributes` passed to Cosmic
Text by `TextPipeline::update_buffer`.

Any text implementation using `bevy_text` must now provide viewport and
rem base values when calling `TextPipeline::update_buffer` or
`create_measure`.

`Text2d` uses the size of the primary window to resolve viewport values
(or `Vec2::splat(1000)` if no primary window is found). This is a
deliberate compromise, a single `Text2d` can be rendered to multiple
viewports using `RenderLayers`, so it's difficult to find a rule for
which viewport size should be chosen.

### Change detection 

`ComputedTextBlock` has two new fields: `uses_viewport_sizes` and
`uses_rem_sizes`, which are set to true in `TextPipeline::update_buffer`
iff any text section in the block uses viewport or rem font sizes,
respectively.

The `ComputedTextBlock::needs_rerender` method has been modified to take
take two bool parameters:
```rust
    pub fn needs_rerender(
        &self,
        is_viewport_size_changed: bool,
        is_rem_size_changed: bool,
    ) -> bool {
        self.needs_rerender
            || (is_viewport_size_changed && self.uses_viewport_sizes)
            || (is_rem_size_changed && self.uses_rem_sizes)
    }
 ```
This ensures that text reupdates will also be scheduled if one of the text section's uses a viewport font size and the local viewport size changed, or if one of the text section's uses a rem font size and the rem size changed.

#### Limitations

There are some limitations because we don't have any sort of font style inheritance yet:

* "rem" units aren't proper rem units, and just based on the value of a resource. 
* "em" units are resolved based on inherited font size, so can't be implemented without inheritance support.

#### Notes

* This PR is quite small and not very technical. Reviewers don't need to be especially familiar with `bevy_text`. Most of the changes are to the examples.

* We could consider using `Val` instead of `FontSize`, then we could use `Val`'s constructor functions which would be much nicer, but some variants might not have sensible interpretations in both UI and Text2d contexts. Also we'd have to make `Val` accessible to `bevy_text`.

## Testing

The changes to the text systems are relatively trivial and easy to understand.  I already added a minor change to the `text` example to use `Vh` font size for the "hello bevy" text in the bottom right corner. If you change the size of the window, you should see the text change size in response. The text initially flickers before it updates because of some unrelated asset/image changes that mean that font textures aren't ready until the frame after the text update that changes the font size.

Most of the example migrations were automated using regular expressions, and there are bound to be mistakes in those changes. It's infeasible to check every single example thoroughly, but it's early enough in the release cycle that I don't think we should be too worried if a few bugs slip in.

---------

Co-authored-by: Kevin Chen <chen.kevin.f@gmail.com>
2026-02-02 22:52:33 +00:00
WaterWhisperer 727a350fc6 Sort the UI examples into sub-dirs (#22727)
# Objective

- Fixes #22644

## Solution

- Create new subdirectories for categorization, and update the paths in
`Cargo.toml` and `README`.

## Testing

- `cargo check --example *`
2026-02-01 18:14:10 +00:00