LR-BEHAV-ACCESS: an empty filmstrip is still a landmark and its reason is read

This commit is contained in:
Nathaniel Ledford
2026-10-29 13:38:03 -04:00
parent 4860892332
commit a0c61edb6e
2 changed files with 32 additions and 1 deletions
@@ -65,7 +65,10 @@ pub(crate) fn filmstrip(app: &mut LightcraftApp, ui: &mut egui::Ui, r: Rect) {
let ppp = ui.ctx().pixels_per_point();
if ids.is_empty() {
let why = if app.session.filter != Default::default() { "No photos match the filters (View → Clear Filters)" } else { "No photos" };
ui.painter().text(r.center(), Align2::CENTER_CENTER, why, t.font(12.5), t.text_dim);
// a label, not painted text, so a screen reader reads the reason; the region keeps the strip navigable
let mut empty = ui.new_child(egui::UiBuilder::new().max_rect(r).layout(egui::Layout::centered_and_justified(egui::Direction::TopDown)));
crate::widgets::announce_region(&empty, egui::accesskit::Role::Region, crate::i18n::tr("Filmstrip"));
empty.add(egui::Label::new(egui::RichText::new(why).font(t.font(12.5)).color(t.text_dim)).selectable(false));
return;
}
let mut child = ui.new_child(egui::UiBuilder::new().max_rect(r.shrink2(vec2(0.0, 4.0))));
+28
View File
@@ -60,3 +60,31 @@ fn the_grid_is_the_main_landmark_in_the_photo_grid() {
assert_eq!(count(&h, Role::Main, "Photos"), 1);
assert_eq!(count(&h, Role::Region, "Filmstrip"), 0, "the grid has no filmstrip");
}
/// A filter that hides every photo leaves the filmstrip drawn with its reason: it stays a landmark
/// and the reason is text a screen reader reads, not paint.
#[test]
fn an_empty_filmstrip_is_still_a_landmark_and_says_why() {
let mut session = lightcraft_engine::Session::with_demo();
session.execute("library.filter", &serde_json::json!({"keyword": "no-such-keyword"})).expect("the filter is set");
assert!(session.visible_cloned().is_empty(), "the filter hides every photo");
let mut app = LightcraftApp::new(session, Services { png: None, ..Default::default() });
app.ui.left_panel = true;
app.ui.view = ViewMode::Detail;
app.ui.right = RightPanel::Edit;
let mut h = Harness::builder().with_size(vec2(1500.0, 950.0)).build_ui_state(
|ui, app: &mut LightcraftApp| {
app.logic(&ui.ctx().clone());
app.ui(ui);
},
app,
);
h.run_steps(10);
assert_eq!(count(&h, Role::Region, "Filmstrip"), 1, "the empty strip is still a landmark");
let said = h
.root()
.children_recursive()
.filter_map(|n| n.accesskit_node().value().or_else(|| n.accesskit_node().label()))
.any(|t| t.starts_with("No photos match the filters"));
assert!(said, "the reason is read, not only painted");
}