Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Merged by Bors] - Integrate AccessKit #6874

Closed
wants to merge 66 commits into from
Closed
Show file tree
Hide file tree
Changes from 64 commits
Commits
Show all changes
66 commits
Select commit Hold shift + click to select a range
0e07c28
Integrate AccessKit.
ndarilek Dec 6, 2022
8b67099
Add support for non-container UI widgets.
ndarilek Nov 15, 2022
269293b
Sync UI focus with AccessKit.
ndarilek Nov 15, 2022
c78a81d
Print out all `ActionRequest` events.
ndarilek Nov 15, 2022
07c6ec8
Clean up focus-handling and attempt to work around more corner cases.…
ndarilek Nov 16, 2022
8503824
Add non-functional example for adding custom `AccessibilityNode`s to …
ndarilek Dec 6, 2022
6c8bc71
Appease Clippy.
ndarilek Dec 6, 2022
3465deb
WIP: use `Mutex` rather than channels for pulling actions.
ndarilek Dec 6, 2022
26444b5
Merge remote-tracking branch 'origin' into accesskit
ndarilek Dec 12, 2022
9a9cf83
Introduce `bevy_a11y` crate.
ndarilek Dec 13, 2022
7d7ac22
Begin decoupling bevy_ui from bevy_winit.
ndarilek Dec 13, 2022
1cf5730
Decouple bevy_ui from bevy_winit and continue integrating bevy_a11y.
ndarilek Dec 13, 2022
0fc80fc
Give structs less generic names.
ndarilek Dec 13, 2022
ebaac9b
Lazily calculate AccessKit updates only when necessary.
ndarilek Dec 14, 2022
058264b
Only run node update logic if nodes/focus changes.
ndarilek Dec 14, 2022
efd9d80
Remove unnecessary logging.
ndarilek Dec 14, 2022
b86a2c3
Perform `u128` conversion first.
ndarilek Dec 14, 2022
b52e587
Remove code simulating keyboard focus-handling until bevy_ui explicit…
ndarilek Dec 14, 2022
06fe868
Remove unnecessary resource initialization.
ndarilek Dec 14, 2022
c503915
Only set focus on tree updates if the window itself has focus.
ndarilek Dec 14, 2022
79bebfa
Use 2 rather than 1 for entity-to-node ID conversions since ID 1 is r…
ndarilek Dec 14, 2022
f84cbf0
Consistently set name of root window.
ndarilek Dec 14, 2022
6ec2a87
Merge remote-tracking branch 'origin' into accesskit
ndarilek Jan 23, 2023
647a408
Merge branch 'main' into accesskit
ndarilek Jan 23, 2023
2f09ebb
Revert accidental formatting change.
ndarilek Jan 23, 2023
3aa8c8e
Bump accesskit_winit dependency.
ndarilek Jan 23, 2023
43db5ac
Restore accidentally-removed code.
ndarilek Jan 23, 2023
f466741
Merge branch 'main' into accesskit
ndarilek Jan 25, 2023
f276404
s/`ResMut`/`NonSendMut`/
ndarilek Jan 25, 2023
791fbe4
Make `WinitActionHandlers` a regular resource.
ndarilek Jan 25, 2023
aac5116
Remove unused function.
ndarilek Jan 25, 2023
9fee1ee
Merge branch 'main' into accesskit
ndarilek Jan 30, 2023
05b03d3
Merge remote-tracking branch 'origin' into accesskit
ndarilek Feb 2, 2023
06714ea
Add crate metadata and documentation.
ndarilek Feb 2, 2023
7894849
Update accessibility nodes on bounds changes.
ndarilek Feb 2, 2023
eafe226
Mirror hierarchies to accessibility tree where possible.
ndarilek Feb 2, 2023
2677ae4
Move `AccessibilityNode` bounds calculation into separate system.
ndarilek Feb 2, 2023
3b75e5e
Add more module-level docs.
ndarilek Feb 3, 2023
69166c6
Add `AccessibilityRequested` resource to track whether accessibility …
ndarilek Feb 3, 2023
1571633
Merge branch 'main' into accesskit
ndarilek Feb 3, 2023
f00c893
Remove unnecessary system since tree updates are no longer pushed on …
ndarilek Feb 3, 2023
6ed0c14
Only generate `TreeUpdate`s if accessibility was requested.
ndarilek Feb 3, 2023
f67de8e
Add comment explaining the use of `Label`.
ndarilek Feb 3, 2023
ca99b51
Use `Option`/branching to minimize performance hit of UI updates.
ndarilek Feb 3, 2023
eb6a30d
Merge branch 'main' into accesskit
ndarilek Feb 3, 2023
3b25d00
Merge branch 'main' into accesskit
ndarilek Feb 6, 2023
7ddfea0
Update to newer AccessKit.
ndarilek Feb 6, 2023
0ac0051
Merge branch 'main' into accesskit
ndarilek Feb 13, 2023
f9f251d
Bump dependencies.
ndarilek Feb 13, 2023
293b240
Update crates/bevy_winit/src/lib.rs
ndarilek Feb 14, 2023
7771ddc
Fix broken link in documentation.
ndarilek Feb 15, 2023
2b6a114
Fix CI errors.
ndarilek Feb 15, 2023
c6e36c1
Fix more conflicts.
ndarilek Feb 15, 2023
a375b56
fix wasm build
mockersf Feb 15, 2023
c4e95bc
Update crates/bevy_a11y/Cargo.toml
ndarilek Feb 15, 2023
2917a86
Add bevy_a11y to publishing script.
ndarilek Feb 15, 2023
6ea06b6
Merge pull request #1 from mockersf/fix-wasm-build
ndarilek Feb 15, 2023
03a89e3
Best-effort attempt at correctly calculating accessibility bounding b…
ndarilek Feb 16, 2023
fed306d
Update crates/bevy_a11y/src/lib.rs
ndarilek Feb 20, 2023
47e8d0e
Reduce nesting.
ndarilek Feb 20, 2023
d7a1011
Feature-gate Unix AccessKit adapter for now.
ndarilek Feb 20, 2023
0349cd7
Merge branch 'main' into accesskit
ndarilek Feb 20, 2023
d9a9adc
Merge branch 'main' into accesskit
ndarilek Feb 20, 2023
5841343
Merge branch 'main' into accesskit
ndarilek Feb 27, 2023
8d43a23
Merge remote-tracking branch 'origin/main' into pr/ndarilek/6874
cart Mar 1, 2023
cc2ed5c
Update cargo features
cart Mar 1, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,10 @@ detailed_trace = ["bevy_internal/detailed_trace"]
# Include tonemapping LUT KTX2 files.
tonemapping_luts = ["bevy_internal/tonemapping_luts"]

# Enable AccessKit on Unix backends (currently only works with experimental
# screen readers and forks.)
accesskit_unix = ["bevy_internal/accesskit_unix"]

[dependencies]
bevy_dylib = { path = "crates/bevy_dylib", version = "0.9.0", default-features = false, optional = true }
bevy_internal = { path = "crates/bevy_internal", version = "0.9.0", default-features = false }
Expand Down
17 changes: 17 additions & 0 deletions crates/bevy_a11y/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
[package]
name = "bevy_a11y"
version = "0.9.0"
edition = "2021"
description = "Provides accessibility support for Bevy Engine"
homepage = "https://bevyengine.org"
repository = "https://github.com/bevyengine/bevy"
license = "MIT OR Apache-2.0"
keywords = ["bevy", "accessibility", "a11y"]

[dependencies]
# bevy
bevy_app = { path = "../bevy_app", version = "0.9.0" }
bevy_derive = { path = "../bevy_derive", version = "0.9.0" }
bevy_ecs = { path = "../bevy_ecs", version = "0.9.0" }

accesskit = "0.10"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This does add a non-trivial number of new dependencies. On linux we now have 358 dependencies, up from 291. That is 61 new deps: a 23% increase.

Obviously accessibility is important. But numbers that big deserve increased scrutiny, even for important features. Where are these deps coming from? What purpose do they serve? Do we need them? What are the compile time implications? What do the dep counts look like on other platforms?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also binary-size implications, especially on WASM. I'm guessing right now WASM is largely unaffected, as these deps appear to be coming from the platform adapters and it doesn't look like there is a WASM adapter.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In addition to the practical / technical issues mentioned above, this is also an optics issue. Bevy is already considered to be "big" and that is a turn off for some people. Substantial dep count increases won't help our case here.

It is definitely hard to add new features without adding new deps. Bevy needs to add new features, therefore our deps will go up. But for all of the reasons listed in this thread we should be working extra hard to drive these numbers down.

70 changes: 70 additions & 0 deletions crates/bevy_a11y/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
//! Accessibility for Bevy

#![warn(missing_docs)]
ndarilek marked this conversation as resolved.
Show resolved Hide resolved
#![forbid(unsafe_code)]

use std::{
num::NonZeroU128,
sync::{atomic::AtomicBool, Arc},
};

pub use accesskit;
use accesskit::{NodeBuilder, NodeId};
use bevy_app::Plugin;
use bevy_derive::{Deref, DerefMut};
use bevy_ecs::{
prelude::{Component, Entity},
system::Resource,
};

/// Resource that tracks whether an assistive technology has requested
/// accessibility information.
///
/// Useful if a third-party plugin needs to conditionally integrate with
/// `AccessKit`
#[derive(Resource, Default, Clone, Debug, Deref, DerefMut)]
pub struct AccessibilityRequested(Arc<AtomicBool>);

/// Component to wrap a [`accesskit::Node`], representing this entity to the platform's
/// accessibility API.
///
/// If an entity has a parent, and that parent also has an `AccessibilityNode`,
/// the entity's node will be a child of the parent's node.
///
/// If the entity doesn't have a parent, or if the immediate parent doesn't have
/// an `AccessibilityNode`, its node will be an immediate child of the primary window.
#[derive(Component, Clone, Deref, DerefMut)]
pub struct AccessibilityNode(pub NodeBuilder);

impl From<NodeBuilder> for AccessibilityNode {
fn from(node: NodeBuilder) -> Self {
Self(node)
}
}

/// Extensions to ease integrating entities with [`AccessKit`](https://accesskit.dev).
pub trait AccessKitEntityExt {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this trait 100% needed and also required to be in the public interface? Seems like it could be an internal utility function.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. Other UIs needing to integrate with AccessKit need a standard way of mapping from entity IDs to accessibility nodes so every view of the accessibility tree is consistent. That ID needs to be non-zero, so for now I just add 1 to the entity ID.

I'll rename it to accessibility_node or similar to make it a bit clearer. If there's some other way of accomplishing this then I'm willing to change it, but I think this is the least brittle, most future-proof, and easiest to integrate with.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, with windows as entities now, it may be possible to make this an implementation detail. Hadn't looked at it in a while but initially it had to add 2 because 1 was reserved for the primary window ID. But with everything sharing the same ID space, I may be able to make it pub(crate). If I can, I will.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unfortunately, this needs to be exposed for UI and other accessibility implementors to agree on an entity-to-AccessKit ID mapping. AccessKit IDs need to be non-zero so it just adds 1.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed: I think this is mandatory for bevy to define.

/// Convert an entity to a stable [`NodeId`].
fn to_node_id(&self) -> NodeId;
}

impl AccessKitEntityExt for Entity {
fn to_node_id(&self) -> NodeId {
let id = NonZeroU128::new(self.to_bits() as u128 + 1);
NodeId(id.unwrap())
}
}

/// Resource representing which entity has keyboard focus, if any.
#[derive(Resource, Default, Deref, DerefMut)]
pub struct Focus(Option<Entity>);

/// Plugin managing non-GUI aspects of integrating with accessibility APIs.
pub struct AccessibilityPlugin;

impl Plugin for AccessibilityPlugin {
fn build(&self, app: &mut bevy_app::App) {
app.init_resource::<AccessibilityRequested>()
.init_resource::<Focus>();
}
}
5 changes: 5 additions & 0 deletions crates/bevy_internal/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -82,10 +82,15 @@ dynamic_linking = ["bevy_diagnostic/dynamic_linking"]
# Enable using a shared stdlib for cxx on Android.
android_shared_stdcxx = ["bevy_audio/android_shared_stdcxx"]

# Enable AccessKit on Unix backends (currently only works with experimental
# screen readers and forks.)
accesskit_unix = ["bevy_winit/accesskit_unix"]

bevy_text = ["dep:bevy_text", "bevy_ui?/bevy_text"]

[dependencies]
# bevy
bevy_a11y = { path = "../bevy_a11y", version = "0.9.0" }
bevy_app = { path = "../bevy_app", version = "0.9.0" }
bevy_core = { path = "../bevy_core", version = "0.9.0" }
bevy_derive = { path = "../bevy_derive", version = "0.9.0" }
Expand Down
3 changes: 2 additions & 1 deletion crates/bevy_internal/src/default_plugins.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,8 @@ impl PluginGroup for DefaultPlugins {
.add(bevy_hierarchy::HierarchyPlugin::default())
.add(bevy_diagnostic::DiagnosticsPlugin::default())
.add(bevy_input::InputPlugin::default())
.add(bevy_window::WindowPlugin::default());
.add(bevy_window::WindowPlugin::default())
.add(bevy_a11y::AccessibilityPlugin);

#[cfg(feature = "bevy_asset")]
{
Expand Down
5 changes: 5 additions & 0 deletions crates/bevy_internal/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@ pub mod prelude;
mod default_plugins;
pub use default_plugins::*;

pub mod a11y {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Module level docs would be super nice here.

//! Integrate with platform accessibility APIs.
pub use bevy_a11y::*;
}

pub mod app {
//! Build bevy apps, create plugins, and read events.
pub use bevy_app::*;
Expand Down
1 change: 1 addition & 0 deletions crates/bevy_ui/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ keywords = ["bevy"]

[dependencies]
# bevy
bevy_a11y = { path = "../bevy_a11y", version = "0.9.0" }
bevy_app = { path = "../bevy_app", version = "0.9.0" }
bevy_asset = { path = "../bevy_asset", version = "0.9.0" }
bevy_core_pipeline = { path = "../bevy_core_pipeline", version = "0.9.0" }
Expand Down
157 changes: 157 additions & 0 deletions crates/bevy_ui/src/accessibility.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
use bevy_a11y::{
accesskit::{NodeBuilder, Rect, Role},
AccessibilityNode,
};
use bevy_app::{App, Plugin};

use bevy_ecs::{
prelude::Entity,
query::{Changed, Or, Without},
system::{Commands, Query},
};
use bevy_hierarchy::Children;

use bevy_render::prelude::Camera;
use bevy_text::Text;
use bevy_transform::prelude::GlobalTransform;

use crate::{
prelude::{Button, Label},
Node, UiImage,
};

fn calc_name(texts: &Query<&Text>, children: &Children) -> Option<Box<str>> {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not clear to me that we should be reading the text here, rather than using the Name component (and encouraging people to write to it).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree in principle, but I'd like to see these sorts of ideas pushed forward in a general UI overhaul. Put in terms more familiar to those of us who work with accessibility, it's better when designed in from the start vs. bolted on later.

To be clear, I'm not critiquing bevy_ui for not being accessible from the start, particularly since bevy_ui is lacking quite a few things and accessibility is in good company. :) I'd just like to see us address these sorts of issues as part of a greater UI refactor of which accessibility is just one part. Without this groundwork, we wouldn't necessarily be able to meaningfully include accessibility as a design consideration when bevy_ui eventually gets more attention.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just curious: Is there a reason this is used for set_name and not set_description or something similar?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mainly because I didn't want to take on fixing bevy_ui's shortcomings in this PR. I needed something to test with, and we don't currently have a way of describing UI widgets in any form. So I calculated a name/title and left it there.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see. And so the shortcoming you're talking about is that bevy_ui doesn't enforce Name components to extract the a11y name from?

If it did, would this function instead be used to extract the node's description?

Copy link
Contributor Author

@ndarilek ndarilek Feb 20, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's more that bevy_ui will eventually need something like Flutter's Semantics class to truly be accessible. Ideally, in that situation, we'll have clearer understandings of how and when we're able to auto-generate names/descriptions, the Semantics component will be nicely integrated with the editor so accessibility properties can be set directly, etc. And I'm trying to take a lighter touch with all those things right now because I don't know what the right answer is.

Also, names and descriptions are very different things, and you don't necessarily want to scattershot the same property value everywhere so e.g. you don't double-announce a name because a screen reader might read a widget like "<name> <description>: button" or similar. Which properties to use and when is fairly complex and differs per widget, but in general setting names is universal and fairly low-hanging fruit. Something more complex I likely wouldn't auto-generate unless the widget semantics clearly call for it.

Ideally, we'll use AccessKit's NodeBuilder or a supported subset of its schema as the core of our Semantics component, and come to consensus about how we automatically fill in properties vs. expecting developers to fill them in themselves.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense, thanks for the explanation!

let mut name = None;
for child in children.iter() {
if let Ok(text) = texts.get(*child) {
let values = text
.sections
.iter()
.map(|v| v.value.to_string())
.collect::<Vec<String>>();
name = Some(values.join(" "));
}
}
name.map(|v| v.into_boxed_str())
}

fn calc_bounds(
camera: Query<(&Camera, &GlobalTransform)>,
mut nodes: Query<
(&mut AccessibilityNode, &Node, &GlobalTransform),
Or<(Changed<Node>, Changed<GlobalTransform>)>,
>,
) {
if let Ok((camera, camera_transform)) = camera.get_single() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There may be more than one camera that meets the requirements of this query. This might need to change to iteration instead of using get_single.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you please either point to a multi-camera UI example, or let me know how to determine which camera to use when calculating the correct translation? I'm trying to avoid taking responsibility for more of bevy_ui's rough edges than I absolutely have to, and I think I'd rather this fail with outliers for now, than have to make these types of decisions on my own. But the examples I've worked with all seem to use a single camera, so...

for (mut accessible, node, transform) in &mut nodes {
if let Some(translation) =
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

style nit: This could use let ... else to avoid indentation.

camera.world_to_viewport(camera_transform, transform.translation())
{
let bounds = Rect::new(
translation.x.into(),
translation.y.into(),
(translation.x + node.calculated_size.x).into(),
(translation.y + node.calculated_size.y).into(),
);
accessible.set_bounds(bounds);
}
}
}
}

fn button_changed(
mut commands: Commands,
mut query: Query<(Entity, &Children, Option<&mut AccessibilityNode>), Changed<Button>>,
texts: Query<&Text>,
) {
for (entity, children, accessible) in &mut query {
let name = calc_name(&texts, children);
if let Some(mut accessible) = accessible {
accessible.set_role(Role::Button);
if let Some(name) = name {
accessible.set_name(name);
} else {
accessible.clear_name();
}
} else {
let mut node = NodeBuilder::new(Role::Button);
if let Some(name) = name {
node.set_name(name);
}
commands
.entity(entity)
.insert(AccessibilityNode::from(node));
}
}
}

fn image_changed(
mut commands: Commands,
mut query: Query<
(Entity, &Children, Option<&mut AccessibilityNode>),
(Changed<UiImage>, Without<Button>),
>,
texts: Query<&Text>,
) {
for (entity, children, accessible) in &mut query {
let name = calc_name(&texts, children);
if let Some(mut accessible) = accessible {
accessible.set_role(Role::Image);
if let Some(name) = name {
accessible.set_name(name);
} else {
accessible.clear_name();
}
} else {
let mut node = NodeBuilder::new(Role::Image);
if let Some(name) = name {
node.set_name(name);
}
commands
.entity(entity)
.insert(AccessibilityNode::from(node));
}
}
}

fn label_changed(
mut commands: Commands,
mut query: Query<(Entity, &Text, Option<&mut AccessibilityNode>), Changed<Label>>,
) {
for (entity, text, accessible) in &mut query {
let values = text
.sections
.iter()
.map(|v| v.value.to_string())
.collect::<Vec<String>>();
let name = Some(values.join(" ").into_boxed_str());
if let Some(mut accessible) = accessible {
accessible.set_role(Role::LabelText);
if let Some(name) = name {
accessible.set_name(name);
} else {
accessible.clear_name();
}
} else {
let mut node = NodeBuilder::new(Role::LabelText);
if let Some(name) = name {
node.set_name(name);
}
commands
.entity(entity)
.insert(AccessibilityNode::from(node));
}
}
}

/// `AccessKit` integration for `bevy_ui`.
pub(crate) struct AccessibilityPlugin;

impl Plugin for AccessibilityPlugin {
fn build(&self, app: &mut App) {
app.add_system(calc_bounds)
.add_system(button_changed)
.add_system(image_changed)
.add_system(label_changed);
}
}
6 changes: 4 additions & 2 deletions crates/bevy_ui/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ mod render;
mod stack;
mod ui_node;

mod accessibility;
pub mod camera_config;
pub mod node_bundles;
pub mod update;
Expand All @@ -27,8 +28,7 @@ pub use ui_node::*;
pub mod prelude {
#[doc(hidden)]
pub use crate::{
camera_config::*, geometry::*, node_bundles::*, ui_node::*, widget::Button, Interaction,
UiScale,
camera_config::*, geometry::*, node_bundles::*, ui_node::*, widget::*, Interaction, UiScale,
};
}

Expand Down Expand Up @@ -102,6 +102,8 @@ impl Plugin for UiPlugin {
.register_type::<UiImage>()
.register_type::<Val>()
.register_type::<widget::Button>()
.register_type::<widget::Label>()
.add_plugin(accessibility::AccessibilityPlugin)
.configure_set(UiSystem::Focus.in_base_set(CoreSet::PreUpdate))
.configure_set(UiSystem::Flex.in_base_set(CoreSet::PostUpdate))
.configure_set(UiSystem::Stack.in_base_set(CoreSet::PostUpdate))
Expand Down
9 changes: 9 additions & 0 deletions crates/bevy_ui/src/widget/label.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
use bevy_ecs::prelude::Component;
use bevy_ecs::reflect::ReflectComponent;
use bevy_reflect::std_traits::ReflectDefault;
use bevy_reflect::Reflect;

/// Marker struct for labels
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: It might be good to indicate why this component should be used. Seems like it's mainly for the Role::Label, but that's not immediately obvious (users may skip this in favor of just relying on Text).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you have any wording suggestions I'm open to them--brain is a bit fried ATM. Alternately I can just remove it in favor of attaching a custom NodeBuilder to those nodes in particular. I added Label before I realized how easy it was to just slap on a custom NodeBuilder and make whatever customizations I needed there.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, I feel like a label is a fairly common UI widget type, and we're going to want this or something like it at some point anyway. So it isn't really an accessibility thing, more a general widget I probably introduced before it's time thing.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't have any wording suggestions off the top of my head. If it's meant to be part of a larger widget ecosystem, then maybe we come back to this (proper documentation) when we're ready to fully implement it? I imagine its usage and design could change a lot between now and when we truly define a "label" widget.

#[derive(Component, Debug, Default, Clone, Copy, Reflect)]
#[reflect(Component, Default)]
pub struct Label;
2 changes: 2 additions & 0 deletions crates/bevy_ui/src/widget/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@

mod button;
mod image;
mod label;
#[cfg(feature = "bevy_text")]
mod text;

pub use button::*;
pub use image::*;
pub use label::*;
#[cfg(feature = "bevy_text")]
pub use text::*;
5 changes: 5 additions & 0 deletions crates/bevy_winit/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,23 @@ keywords = ["bevy"]
trace = []
wayland = ["winit/wayland"]
x11 = ["winit/x11"]
accesskit_unix = ["accesskit_winit/accesskit_unix"]

[dependencies]
# bevy
bevy_a11y = { path = "../bevy_a11y", version = "0.9.0" }
bevy_app = { path = "../bevy_app", version = "0.9.0" }
bevy_derive = { path = "../bevy_derive", version = "0.9.0" }
bevy_ecs = { path = "../bevy_ecs", version = "0.9.0" }
bevy_hierarchy = { path = "../bevy_hierarchy", version = "0.9.0" }
bevy_input = { path = "../bevy_input", version = "0.9.0" }
bevy_math = { path = "../bevy_math", version = "0.9.0" }
bevy_window = { path = "../bevy_window", version = "0.9.0" }
bevy_utils = { path = "../bevy_utils", version = "0.9.0" }

# other
winit = { version = "0.28", default-features = false }
accesskit_winit = { version = "0.12", default-features = false }
approx = { version = "0.5", default-features = false }
raw-window-handle = "0.5"

Expand Down
Loading