mirror of
https://github.com/storytold/figcraft.git
synced 2026-11-13 22:02:38 +00:00
M5: a locked layer in Select layer says so to assistive technology (#1560)
The padlock in a Select layer row is only paint, so a screen reader could not tell a locked layer from the rest. A locked row now gets the description "locked" (the same string the Layers panel adds), joined with any description the row already has. New a11y::describe sets a description on an existing node without touching its label or role. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Model-Effort: Opus 5.5 drove; Opus 5.5 briefed; Sonnet 5.5 wrote at medium
This commit is contained in:
1 parent
87f7b7d944
commit
39e3496fef
3 files changed
+37
No files matched your search
@@ -995,6 +995,18 @@ pub fn disabled(resp: &Response) {
|
||||
node(resp, "", |n| n.set_disabled());
|
||||
}
|
||||
|
||||
/// `resp`'s node also says `text` (a menu row's state, e.g. "locked"), after any description
|
||||
/// already set (joined with ", ").
|
||||
pub fn describe(resp: &Response, text: &str) {
|
||||
node(resp, "", |n| {
|
||||
let d = match n.description() {
|
||||
Some(old) if !old.is_empty() => format!("{old}, {text}"),
|
||||
_ => text.to_string(),
|
||||
};
|
||||
n.set_description(d);
|
||||
});
|
||||
}
|
||||
|
||||
/// What a layer row says besides its name.
|
||||
pub struct RowInfo<'a> {
|
||||
/// The layer's type ("Frame", "Text").
|
||||
|
||||
@@ -189,6 +189,28 @@ fn select_layer_marks_locked_layers_with_a_padlock_and_picks_them() {
|
||||
let _ = lower;
|
||||
}
|
||||
|
||||
/// The padlock is only paint: the locked row says "locked" to assistive technology too.
|
||||
#[test]
|
||||
fn select_layer_locked_row_is_described_as_locked() {
|
||||
let (mut u, _, _) = overlap_ui();
|
||||
let at = u.app.to_screen(150.0, 150.0);
|
||||
crate::canvas::open_context_menu(&mut u.app, at, false);
|
||||
u.app.session.set_selection(vec![]);
|
||||
crate::menus::open_select_layer(&u.ctx, true);
|
||||
u.ctx.enable_accesskit();
|
||||
u.frame(vec![]);
|
||||
let nodes: Vec<egui::accesskit::Node> =
|
||||
u.frame_output(vec![]).platform_output.accesskit_update.expect("an AccessKit update").nodes.into_iter().map(|(_, n)| n).collect();
|
||||
let row = |name: &str| {
|
||||
nodes
|
||||
.iter()
|
||||
.find(|n| n.role() == egui::accesskit::Role::MenuItem && n.label() == Some(name))
|
||||
.unwrap_or_else(|| panic!("no menu row {name:?}"))
|
||||
};
|
||||
assert!(row("Upper").description().is_some_and(|d| d.contains("locked")), "the locked row says locked");
|
||||
assert!(!row("Lower").description().is_some_and(|d| d.contains("locked")), "the other row doesn't");
|
||||
}
|
||||
|
||||
/// Measured on a single locked layer only (Figma's web app, 2026-11-10): the least certain rule.
|
||||
#[test]
|
||||
fn select_layer_needs_more_than_one_layer_under_the_pointer() {
|
||||
|
||||
@@ -408,6 +408,9 @@ pub(super) fn indented_item(ui: &mut Ui, label: &str, shortcut: &str, enabled: b
|
||||
if !enabled {
|
||||
a11y::disabled(&resp);
|
||||
}
|
||||
if locked {
|
||||
a11y::describe(&resp, i18n::tr("locked"));
|
||||
}
|
||||
// The keyboard's item is highlighted like the hovered one.
|
||||
a11y::own_focus(&resp);
|
||||
let hov = plain_row_hover(ui, &resp) && enabled;
|
||||
|
||||
Reference in new issue
Block a user