Enable accessibility features for the button example (#18749)
# Objective Accessibility features don't work with the UI `button` example because `InputFocus` must be set for the accessibility systems to recognise the button. Fixes #18760 ## Solution * Set the button entity as the `InputFocus` when it is hovered or pressed. * Call `set_changed` on the `Button` component when the button's state changes to hovered or pressed (the accessibility system's only update the button's state when the `Button` component is marked as changed). ## Testing Install NVDA, it should say "hover" when the button is hovered and "pressed" when the button is pressed. The bounds of the accessibility node are reported incorrectly. I thought we fixed this, I'll take another look at it. It's not a problem with this PR.
This commit is contained in:
parent
ed0266b5a6
commit
3edacb5e46
@ -1,13 +1,15 @@
|
|||||||
//! This example illustrates how to create a button that changes color and text based on its
|
//! This example illustrates how to create a button that changes color and text based on its
|
||||||
//! interaction state.
|
//! interaction state.
|
||||||
|
|
||||||
use bevy::{color::palettes::basic::*, prelude::*, winit::WinitSettings};
|
use bevy::{color::palettes::basic::*, input_focus::InputFocus, prelude::*, winit::WinitSettings};
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
App::new()
|
App::new()
|
||||||
.add_plugins(DefaultPlugins)
|
.add_plugins(DefaultPlugins)
|
||||||
// Only run the app when there is user input. This will significantly reduce CPU/GPU use.
|
// Only run the app when there is user input. This will significantly reduce CPU/GPU use.
|
||||||
.insert_resource(WinitSettings::desktop_app())
|
.insert_resource(WinitSettings::desktop_app())
|
||||||
|
// `InputFocus` must be set for accessibility to recognize the button.
|
||||||
|
.init_resource::<InputFocus>()
|
||||||
.add_systems(Startup, setup)
|
.add_systems(Startup, setup)
|
||||||
.add_systems(Update, button_system)
|
.add_systems(Update, button_system)
|
||||||
.run();
|
.run();
|
||||||
@ -18,31 +20,44 @@ const HOVERED_BUTTON: Color = Color::srgb(0.25, 0.25, 0.25);
|
|||||||
const PRESSED_BUTTON: Color = Color::srgb(0.35, 0.75, 0.35);
|
const PRESSED_BUTTON: Color = Color::srgb(0.35, 0.75, 0.35);
|
||||||
|
|
||||||
fn button_system(
|
fn button_system(
|
||||||
|
mut input_focus: ResMut<InputFocus>,
|
||||||
mut interaction_query: Query<
|
mut interaction_query: Query<
|
||||||
(
|
(
|
||||||
|
Entity,
|
||||||
&Interaction,
|
&Interaction,
|
||||||
&mut BackgroundColor,
|
&mut BackgroundColor,
|
||||||
&mut BorderColor,
|
&mut BorderColor,
|
||||||
|
&mut Button,
|
||||||
&Children,
|
&Children,
|
||||||
),
|
),
|
||||||
(Changed<Interaction>, With<Button>),
|
Changed<Interaction>,
|
||||||
>,
|
>,
|
||||||
mut text_query: Query<&mut Text>,
|
mut text_query: Query<&mut Text>,
|
||||||
) {
|
) {
|
||||||
for (interaction, mut color, mut border_color, children) in &mut interaction_query {
|
for (entity, interaction, mut color, mut border_color, mut button, children) in
|
||||||
|
&mut interaction_query
|
||||||
|
{
|
||||||
let mut text = text_query.get_mut(children[0]).unwrap();
|
let mut text = text_query.get_mut(children[0]).unwrap();
|
||||||
|
|
||||||
match *interaction {
|
match *interaction {
|
||||||
Interaction::Pressed => {
|
Interaction::Pressed => {
|
||||||
|
input_focus.set(entity);
|
||||||
**text = "Press".to_string();
|
**text = "Press".to_string();
|
||||||
*color = PRESSED_BUTTON.into();
|
*color = PRESSED_BUTTON.into();
|
||||||
border_color.0 = RED.into();
|
border_color.0 = RED.into();
|
||||||
|
|
||||||
|
// The accessibility system's only update the button's state when the `Button` component is marked as changed.
|
||||||
|
button.set_changed();
|
||||||
}
|
}
|
||||||
Interaction::Hovered => {
|
Interaction::Hovered => {
|
||||||
|
input_focus.set(entity);
|
||||||
**text = "Hover".to_string();
|
**text = "Hover".to_string();
|
||||||
*color = HOVERED_BUTTON.into();
|
*color = HOVERED_BUTTON.into();
|
||||||
border_color.0 = Color::WHITE;
|
border_color.0 = Color::WHITE;
|
||||||
|
button.set_changed();
|
||||||
}
|
}
|
||||||
Interaction::None => {
|
Interaction::None => {
|
||||||
|
input_focus.clear();
|
||||||
**text = "Button".to_string();
|
**text = "Button".to_string();
|
||||||
*color = NORMAL_BUTTON.into();
|
*color = NORMAL_BUTTON.into();
|
||||||
border_color.0 = Color::BLACK;
|
border_color.0 = Color::BLACK;
|
||||||
|
Loading…
Reference in New Issue
Block a user