Skip to content

Commit

Permalink
Add accessibility to ProgressBar and Spinner (emilk#4139)
Browse files Browse the repository at this point in the history
- Introduces `WidgetType::ProgressIndicator` and maps it to the
corresponding AccessKit role.
- A `Spinner` is now exposed as a widget indicating a progress for which
a completion state is not known.
- On the other hand, a `ProgressBar` reports a completion state and can
possibly be labeled. Note that a label is not used if not explicitly
asked by the user, as it would be redundant information. Assistive
technologies prefer the numerical value so they can, for instance, emit
beeps of which the frequency rise as the completion state increase. I
had to call `floor` on the progression as it seems all the ATs I tested
would round the value, hence reporting something different than what is
displayed on the label.
  • Loading branch information
DataTriny authored Mar 8, 2024
1 parent a1d5145 commit 76411b5
Show file tree
Hide file tree
Showing 5 changed files with 17 additions and 1 deletion.
1 change: 1 addition & 0 deletions crates/egui/src/data/output.rs
Original file line number Diff line number Diff line change
Expand Up @@ -633,6 +633,7 @@ impl WidgetInfo {
WidgetType::ColorButton => "color button",
WidgetType::ImageButton => "image button",
WidgetType::CollapsingHeader => "collapsing header",
WidgetType::ProgressIndicator => "progress indicator",
WidgetType::Label | WidgetType::Other => "",
};

Expand Down
2 changes: 2 additions & 0 deletions crates/egui/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -643,6 +643,8 @@ pub enum WidgetType {

CollapsingHeader,

ProgressIndicator,

/// If you cannot fit any of the above slots.
///
/// If this is something you think should be added, file an issue.
Expand Down
1 change: 1 addition & 0 deletions crates/egui/src/response.rs
Original file line number Diff line number Diff line change
Expand Up @@ -783,6 +783,7 @@ impl Response {
WidgetType::Slider => Role::Slider,
WidgetType::DragValue => Role::SpinButton,
WidgetType::ColorButton => Role::ColorWell,
WidgetType::ProgressIndicator => Role::ProgressIndicator,
WidgetType::Other => Role::Unknown,
});
if let Some(label) = info.label {
Expand Down
11 changes: 11 additions & 0 deletions crates/egui/src/widgets/progress_bar.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,17 @@ impl Widget for ProgressBar {
let (outer_rect, response) =
ui.allocate_exact_size(vec2(desired_width, height), Sense::hover());

response.widget_info(|| {
let mut info = if let Some(ProgressBarText::Custom(text)) = &text {
WidgetInfo::labeled(WidgetType::ProgressIndicator, text.text())
} else {
WidgetInfo::new(WidgetType::ProgressIndicator)
};
info.value = Some((progress as f64 * 100.0).floor());

info
});

if ui.is_rect_visible(response.rect) {
if animate {
ui.ctx().request_repaint();
Expand Down
3 changes: 2 additions & 1 deletion crates/egui/src/widgets/spinner.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use epaint::{emath::lerp, vec2, Color32, Pos2, Rect, Shape, Stroke};

use crate::{Response, Sense, Ui, Widget};
use crate::{Response, Sense, Ui, Widget, WidgetInfo, WidgetType};

/// A spinner widget used to indicate loading.
///
Expand Down Expand Up @@ -66,6 +66,7 @@ impl Widget for Spinner {
.size
.unwrap_or_else(|| ui.style().spacing.interact_size.y);
let (rect, response) = ui.allocate_exact_size(vec2(size, size), Sense::hover());
response.widget_info(|| WidgetInfo::new(WidgetType::ProgressIndicator));
self.paint_at(ui, rect);

response
Expand Down

0 comments on commit 76411b5

Please sign in to comment.